Matplotlib multi-line plot coloured by date

Viewed 44

I have a simple XY plot of some data (variable A vs variable B) in which each over-plotted line shows data for data for different time periods. I want to be able to colour each line (series) from a colourmap based on its date (I actually want colour by month), not just the order in which the data is added. Any thoughts on how to easily do this? Everything I read seems geared up to picking the colour based on the loop iterator, not the data itself.

My data looks like this (this is just a snippet):

DATE (YYYY-MM-DDTHH:MI:SSZ) A       B
2019-11-28T13:39:00Z        8.4     5.753
2019-11-28T13:39:00Z        10.5    5.755
2019-11-28T13:39:00Z        12.4    5.753
2019-11-28T13:39:00Z        14.5    5.753
2019-11-28T13:39:00Z        16.7    5.753
2019-11-28T13:39:00Z        18.5    5.752
2019-11-28T13:39:00Z        20.2    5.75
2019-11-30T13:59:30Z        9.1     6.167
2019-11-30T13:59:30Z        10.2    6.165
2019-11-30T13:59:30Z        10.9    6.167
2019-11-30T13:59:30Z        11.8    6.166
2019-11-30T13:59:30Z        12.9    6.166
2019-11-30T13:59:30Z        13.8    6.168
2019-11-30T13:59:30Z        14.9    6.166
2019-11-30T13:59:30Z        15.9    6.165
2019-11-30T13:59:30Z        17      6.166
2019-11-30T13:59:30Z        17.9    6.166
2019-11-30T13:59:30Z        18.9    6.166
2019-11-30T13:59:30Z        20      6.168
2019-11-30T13:59:30Z        1.8     6.159
2019-11-30T13:59:30Z        2.8     6.16
2019-11-30T13:59:30Z        4       6.161
2019-11-30T13:59:30Z        5.1     6.161
2019-11-30T13:59:30Z        6.1     6.161
2019-11-30T13:59:30Z        6.9     6.165
2019-11-30T13:59:30Z        8.1     6.168
2019-12-03T13:34:30Z        3.2     5.716
2019-12-03T13:34:30Z        3.8     5.715
2019-12-03T13:34:30Z        4.8     5.714
2019-12-03T13:34:30Z        5.9     5.715
2019-12-03T13:34:30Z        7.1     5.714
2019-12-03T13:34:30Z        8.1     5.715
2019-12-03T13:34:30Z        8.8     5.722
2019-12-03T13:34:30Z        9.8     5.722
2019-12-03T13:34:30Z        10.9    5.721
2019-12-03T13:34:30Z        11.9    5.722
2019-12-03T13:34:30Z        12.9    5.722
2019-12-03T13:34:30Z        14      5.726
2019-12-03T13:34:30Z        15.3    5.728
2019-12-03T13:34:30Z        16.1    5.727
2019-12-03T13:34:30Z        16.9    5.727
2019-12-03T13:34:30Z        17.8    5.726
2019-12-03T13:34:30Z        18.9    5.728
2019-12-03T13:34:30Z        20      5.728
1 Answers

Here is an "ugly" attempt you might find useful built on the Stack Overflow posts "Matplotlib: Different colors for each date, labelled via colorbar" and "Color Map of Date as String in Python":

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

from datetime import datetime
from mpl_toolkits.axes_grid1 import make_axes_locatable

if __name__ == "__main__":

    df = pd.read_csv("data.txt", delim_whitespace=True)

    # Change format time
    df['DATE SIMPLE'] = pd.to_datetime(df['DATE(YYYY-MM-DDTHH:MI:SSZ)']).dt.strftime('%d-%m-%Y')

    # Add colormap
    cmap = plt.get_cmap("viridis")
    colors = [cmap(int(i)) for i in np.linspace(0, cmap.N, len(df))]

    # Start figure
    fig, ax = plt.subplots()

    # Format time for ticks colorbar
    loc = mdates.AutoDateLocator(minticks=5, maxticks=7)
    plt_time = [mdates.date2num(datetime.strptime(timestamp, "%d-%m-%Y")) for timestamp in df['DATE SIMPLE']]

    # Plot XY using matplotlib time for color (plt_time) so the colorbar understands the ticks later
    sc = ax.scatter(x=df["A"], y=df["B"], c=plt_time)
    ax.set_xlabel("A")
    ax.set_ylabel("B")

    # Add colorbar to graph
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("bottom", size="5%", pad=0.50)
    cbar = fig.colorbar(sc, cax=cax, orientation='horizontal', ticks=loc,
                        format=mdates.DateFormatter("%d-%m-%Y"), label="Date (Day-Month-Year)")

    # The ugly part: 'Recolor' the scatter plot with the colors we calculated earlier
    ax.scatter(x=df["A"], y=df["B"], c=colors)
    plt.show()

enter image description here

Related