Reputation: 1092
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:
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')
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
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()
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()
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()
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()
Upvotes: 1