racerX
racerX

Reputation: 1092

Plotting a time series with markers colored by weekday and a legend

I have a data frame with index as the date. The columns are different time series and I have added another column to mark which weekday the particular observation belongs to. Something like this:

enter image description here

What I want to do is:

a) plot a time series, say Series 1, add markers to the plot and color them by the weekday. I have got the 2 plots using plt.scatter and plt.plot:

plt.scatter(x = df.index, y = df['Series1'], c = df['day'])
plt.plot(df.index, df['Series1'], marker = 'o')

enter image description here enter image description here

However, I am unable to add a legend to the first figure. To the second figure I am unable to add either different colored markers or the legend. Can someone help out.

b) If I can achieve a), then I'd like to plot all three series on the same figure.

Thanks!

Upvotes: 2

Views: 2357

Answers (1)

JahKnows
JahKnows

Reputation: 2706

Yes this is all possible! So first let's get all three time series on the same plot

import matplotlib.pyplot as plt

plt.figure()
plt.subplot(1,1,1)
line1, = plt.plot(df.index, df['Series1'])
line2, = plt.plot(df.index, df['Series2'])
line3, = plt.plot(df.index, df['Series3'])

plt.scatter(df.index, df['Series1'], c = df['day'], marker = 'o')
plt.scatter(df.index, df['Series2'], c = df['day'], marker = 'v')
plt.scatter(df.index, df['Series3'], c = df['day'], marker = 'x')

plt.legend(handles=[line1, line2, line3])
plt.show()

enter image description here


If you want to make sure that the markers are in front of the lines in order to get a cleaner plot we can use the zorder property.

import matplotlib.pyplot as plt

plt.figure()
plt.subplot(1,1,1)
line1, = plt.plot(df.index, df['Series1'], zorder=1)
line2, = plt.plot(df.index, df['Series2'], zorder=1)
line3, = plt.plot(df.index, df['Series3'], zorder=1)

plt.scatter(df.index, df['Series1'], c = df['day'], marker = 'o', s = 100, zorder=2)
plt.scatter(df.index, df['Series2'], c = df['day'], marker = 'v', s = 100, zorder=2)
plt.scatter(df.index, df['Series3'], c = df['day'], marker = 'x', s = 100, zorder=2)

plt.legend(handles=[line1, line2, line3])
plt.show()

enter image description here


You can show the difference in days using a colorbar

import matplotlib.pyplot as plt

plt.figure()
plt.subplot(1,1,1)
line1, = plt.plot(df.index, df['Series1'], zorder=1)
line2, = plt.plot(df.index, df['Series2'], zorder=1)
line3, = plt.plot(df.index, df['Series3'], zorder=1)

plt.scatter(df.index, df['Series1'], c = df['day'], marker = 'o', s = 100, zorder=2)
plt.scatter(df.index, df['Series2'], c = df['day'], marker = 'v', s = 100, zorder=2)
plt.scatter(df.index, df['Series3'], c = df['day'], marker = 'x', s = 100, zorder=2)

plt.legend(handles=[line1, line2, line3])
plt.colorbar()
plt.show()

enter image description here


If you want the legend to contain the color associated with the different days then you can make a custom colormap and then have a custom legend as

from matplotlib.patches import Patch
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt

# define the colormap
cmap = plt.cm.jet
cmaplist = [cmap(i) for i in range(1,cmap.N,cmap.N//max(df['day']))]

plt.figure()
plt.subplot(1,1,1)
line1, = plt.plot(df.index, df['Series1'], zorder=1)
line2, = plt.plot(df.index, df['Series2'], zorder=1)
line3, = plt.plot(df.index, df['Series3'], zorder=1)

plt.scatter(df.index, df['Series1'], c = df['day'], cmap='jet', marker = 'o', s = 100, zorder=2)
plt.scatter(df.index, df['Series2'], c = df['day'], cmap='jet', marker = 'v', s = 100, zorder=2)
plt.scatter(df.index, df['Series3'], c = df['day'], cmap='jet', marker = 'x', s = 100, zorder=2)

legend_elements = [Line2D([0], [0], color='b', lw=4, label='Line'),
                   Line2D([0], [0], marker='o', color='w', label='Scatter',
                          markerfacecolor='g', markersize=15),
                   Patch(facecolor='orange', edgecolor='r',
                         label='Color Patch')]
legend_elements = []
for ix, i in enumerate(df['day']):
    temp = Line2D([0], [0], color = cmaplist[i-1][0:3], lw=4, label=str(i))
    legend_elements.append(temp)


plt.legend(handles=legend_elements)
plt.show()

enter image description here

Upvotes: 1

Related Questions