22

I want to plot two time series on the same plot with same x-axis and secondary y-axis. I have somehow achieved this, but two legends are overlapping and is unable to give label to x-axis and secondary y-axis.I tried putting two legend at upper-left and upper-right, but it is still not working.

Code:

plt.figure(figsize=(12,5))

# Number of request every 10 minutes
log_10minutely_count_Series = log_df['IP'].resample('10min').count()
log_10minutely_count_Series.name="Count"
log_10minutely_count_Series.plot(color='blue', grid=True)
plt.legend(loc='upper left')
plt.xlabel('Number of request ever 10 minute')

# Sum of response size over each 10 minute
log_10minutely_sum_Series = log_df['Bytes'].resample('10min').sum()
log_10minutely_sum_Series.name = 'Sum'
log_10minutely_sum_Series.plot(color='red',grid=True, secondary_y=True)
plt.legend(loc='upper right')
plt.show()

enter image description here

Thanks in advance

Om Prakash
  • 2,675
  • 4
  • 29
  • 50

2 Answers2

28

The following solutions work for me. The first places both lines in one legend, the second splits lines into two legends, similar to what you are trying above.

Here is my dataframe

ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list('ABCD'))

One legend solution, credit to this StackOverflow post

plt.figure(figsize=(12,5))
plt.xlabel('Number of requests every 10 minutes')

ax1 = df.A.plot(color='blue', grid=True, label='Count')
ax2 = df.B.plot(color='red', grid=True, secondary_y=True, label='Sum')

h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()


plt.legend(h1+h2, l1+l2, loc=2)
plt.show()

One legend matplotlib plot

Split legend solution

plt.figure(figsize=(12,5))
plt.xlabel('Number of requests every 10 minutes')

ax1 = df.A.plot(color='blue', grid=True, label='Count')
ax2 = df.B.plot(color='red', grid=True, secondary_y=True, label='Sum')

ax1.legend(loc=1)
ax2.legend(loc=2)

plt.show()

Split legend matplotlib plot

Josh
  • 2,767
  • 1
  • 27
  • 31
  • For the split-legend plot, it's better to interchange the legends' `loc`s, because loc=1 is for top right, and the right-y-axis is the secondary y-axis, while loc=2 is for top left (closer to the primary y-axis). See the docs for legend: https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html – Benjamin Wang Feb 22 '23 at 14:20
10

It can be as simple as:

df.loc[:,['A','B']].plot(secondary_y=['B'], mark_right=False, figsize = (20,5), grid=True)

mark_right=False means that 'B' label is on the left axis.

Sarah
  • 1,854
  • 17
  • 18