I can plot a dataframe (2 "Y" values) and add vertical lines (2) to the plot, and I can specify custom legend text for either the Y values OR the vertical lines, but not both at the same time.
import pandas as pd
import matplotlib.pyplot as plt
d = {'x' : [1., 2., 3., 4.], 'y1' : [8., 6., 4., 2.], 'y2' : [-4., 13., 2.2, -1.1]}
df = pd.DataFrame(d)
ax = df.plot(x='x', y=['y1'], linestyle='-', color='b')
df.plot(x='x', y=['y2'], linestyle='--', color='y', ax=ax)
ax.legend(labels=['y1custom', 'y2custom'])
plt.axvline(x=1.5, color='r', linestyle='--', label='vline1.5custom')
plt.axvline(x=3.5, color='k', linestyle='--', label='vline3.5custom')
plt.legend() # <---- comment out....or not....for different effects
plt.show()
A key line in the code is "plt.legend()". With it in the code, I get this (note legend has dataframe column labels "y1" and "y2" instead of my desired custom labels):
With "plt.legend()" removed, I get this (legend has my custom labels for the dataframe values only, legend for vertical lines does not even appear!):
How can I get the best of both worlds, specifically the following (in whatever order) for my legend?:
y1custom
y2custom
vline1.5custom
vline3.5custom
Sure I could rename the columns of the dataframe first, but...ugh! There must be a better way.
By using axvline() In matplotlib, by using the axvline() method we can create multiple vertical lines in the plot.
To plot a vertical line with pyplot, you can use the axvline() function. In this syntax: x is the coordinate for the x-axis. This point is from where the line would be generated vertically. ymin is the bottom of the plot; ymax is the top of the plot.
Each call to legend()
overwrites the initially created legend. So you need to create one single legend with all the desired labels in.
This means you can get the current labels via ax.get_legend_handles_labels()
and replace those you do not like with something else. Then specify the new list of labels when calling legend()
.
import pandas as pd
import matplotlib.pyplot as plt
d = {'x' : [1., 2., 3., 4.], 'y1' : [8., 6., 4., 2.], 'y2' : [-4., 13., 2.2, -1.1]}
df = pd.DataFrame(d)
ax = df.plot(x='x', y=['y1'], linestyle='-', color='b')
df.plot(x='x', y=['y2'], linestyle='--', color='y', ax=ax)
ax.axvline(x=1.5, color='r', linestyle='--', label='vline1.5custom')
ax.axvline(x=3.5, color='k', linestyle='--', label='vline3.5custom')
h,labels = ax.get_legend_handles_labels()
labels[:2] = ['y1custom','y2custom']
ax.legend(labels=labels)
plt.show()
label
can be passed to plot()
as long as you specify the column being plotted:
import pandas as pd
import matplotlib.pyplot as plt
d = {'x' : [1., 2., 3., 4.], 'y1' : [8., 6., 4., 2.], 'y2' : [-4., 13., 2.2, -1.1]}
df = pd.DataFrame(d)
ax = df['y1'].plot(x='x', linestyle='-', color='b', label='y1custom')
df['y2'].plot(x='x', linestyle='--', color='y', ax=ax, label='y2custom')
plt.axvline(x=1.5, color='r', linestyle='--', label='vline1.5custom')
plt.axvline(x=3.5, color='k', linestyle='--', label='vline3.5custom')
plt.legend()
plt.show()
This approach avoids having to mess around with the legend afterwards:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With