Reputation: 51
I'm a new user of matplotlib
. I have already learned the basics of plotting data in matplotlib. But I still cannot understand how I can plot multiple time series data as follows:
It is also important for me that the plot contained a legend.
Data for example:
import pandas as pd
from io import StringIO
from matplotlib import pyplot as plt
data_str = '''time x1 x2 x3 x4
01.01.1984 100 -50 50 54
01.02.1984 200 -20 180 7
01.03.1984 250 -100 150 442413
01.04.1984 300 -50 250 7
01.05.1984 250 -150 100 403
01.06.1984 300 -200 100 148
01.07.1984 200 -100 100 1096'''
df = pd.read_csv(StringIO(data_str), delim_whitespace=True)
df['time'] = pd.to_datetime(df['time'], format='%d.%m.%Y')
df = df.set_index('time')
ax = df['x3'].plot(grid=True, figsize=(10, 6), color='tab:grey', linewidth=4)
ax.bar(height=df['x1'], x=df.index, color='tab:blue', width=0.3, zorder=2, label='x1')
ax.bar(height=df['x2'], x=df.index, color='tab:orange', width=0.3, zorder=2, label='x2')
ax2 = ax.twinx()
ax2.set_yscale('log')
ax2.invert_yaxis()
df['x4'].plot.line(ax=ax2, color='gold', label='x4 (right)', linewidth=4)
ax.axhline(linewidth=1, color='black')
ax.set_xlabel('time', fontsize=16)
plt.xticks(size = 16)
plt.yticks(size = 16)
handles1, labels1 = ax.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
handles = handles1[1:] + handles1[:1] + handles2 # handles1 is reordered because it uses the line before the bars
labels = labels1[1:] + labels1[:1] + labels2
#order = [0,1,2,3]
ax.legend([handles[idx] for idx in order],[labels[idx] for idx in order],
loc='upper center', bbox_to_anchor=(0.5, -0.2),
fancybox=True, shadow=True, ncol=5,
prop={'size': 16})
#plt.xlim(['1983-12-01', '1984-08-01'])
plt.show()
Upvotes: 0
Views: 1219
Reputation: 80574
Explaining each and every step is out of the scope of a stackoverflow answer. A good starting point are the online tutorials. Also, the suggested plot is quite complicated for a beginner's plot.
Some examples of functions used:
pd.read_csv(filename, ...)
reads in data from a csv fileStringIO(data_str)
is a way to mimic a file with reading from a stringplt.subplots
creates a figure (fig
) and subplots (referred to as ax
) to plot ondf['x1'].plot.bar(...)
is a way to plot a bar plot with pandasdf['x3'].plot.line(...)
is a way to plot a line plot with pandasax1.twinx()
creates the y-axis at the rightimport pandas as pd
from io import StringIO
from matplotlib import pyplot as plt
data_str = '''time x1 x2 x3 x4
01.01.1984 100 -50 50 54
01.02.1984 200 -20 180 7
01.03.1984 250 -100 150 442413
01.04.1984 300 -50 250 7
01.05.1984 250 -150 100 403
01.06.1984 300 -200 100 148
01.07.1984 200 -100 100 1096'''
df = pd.read_csv(StringIO(data_str), delim_whitespace=True)
fig, ax1 = plt.subplots(figsize=(10, 4))
ax1.axhline(0, color='black', lw=2) # draw a long horizontal line at y=0
df = df.set_index('time')
df['x1'].plot.bar(ax=ax1, color='skyblue', label='x1')
df['x2'].plot.bar(ax=ax1, color='darkorange', label='x2')
df['x3'].plot.line(ax=ax1, color='slategray', label='x3')
ax2 = ax1.twinx()
ax2.set_yscale('log')
df['x4'].plot.line(ax=ax2, color='gold', label='x4 (right)')
handles1, labels1 = ax1.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
handles = handles1[1:] + handles1[:1] + handles2 # handles1 is reordered because it uses the line before the bars
labels = labels1[1:] + labels1[:1] + labels2
ax1.legend(handles, labels, loc='upper center', bbox_to_anchor=(0.5, -0.1), ncol=len(handles))
ax1.set_xlabel('')
plt.tight_layout()
plt.show()
Upvotes: 2
Reputation: 140
A simple way of plotting multiple series in one plot (from a Pandas Data Frame, df), using a second y-axis is as follows:
df = pd.DataFrame({'time':[1,2,3,4,5,6,7],
'x1':[100, 200, 250, 300, 250, 300, 200],
'x2':[-50,-20,-100,-50, -150, -200, -100],
'x3':[50, 180, 150, 250, 100, 100, 100],
'x4':[54, 7, 442413, 7, 403, 148, 1096]})
plt.figure()
df.x1.plot.bar()
df.x2.plot.bar(color='red')
df.x3.plot.line(color='red')
df.x4.plot.line(color='green', secondary_y=True)
Upvotes: 1