Issue
So basically I'm trying to plot the lap time of 2 F1 drivers and I'd like to show when the Safety Car is out. By the way, I can't show in the same time a legend where I can see, the drivers' name and the Safety Car deployed all at once. I have the same issue to change to marker on the lap where the driver is pitting to change tires.
Here are the lists which are used in the code :
lap=[1, 2, 3, 4, 5, 6, 7, 8, 9]
info=['SC', 'SC', 'SC', None, None, None, None, None, None]
time_lec=[145.323, 141.062, 142.84, 145.489, 136.873, 99.585, 94.848, 92.511, 91.679]
time_nor=[142.471, 139.843, 147.079, 141.984, 130.516, 104.428, 98.389, 94.898, 93.029]
info_lec=[None, None, None, None, None, 'P', None, None, None]
info_nor=[None, None, None, None, 'P', None, None, None, None]
Here is the code to display the drivers legend:
import matplotlib.pyplot as plt
for i in range(0,len(info)):
if info[i]=='SC':
plt.axvspan(i+1,i+2,facecolor='yellow',alpha=0.5) #Display when Safety Car is deployed
if info_lec[i]=='P': #Remove time lost during pitstop
time_lec[i]=time_lec[i]-25
if info_nor[i]=='P':
time_nor[i]=time_nor[i]-25
plt.plot(lap,time_lec,'.:r',label='Leclerc',linewidth=1.2)
plt.plot(lap,time_nor,'.:b',label='Norris',linewidth=1.2)
for i in range(0,len(info)): #Displaying the lap where the driver is pitting (to change tires)
if info_lec[i]=='P':
plt.plot(lap[i],time_lec[i],'xr')
if info_nor[i]=='P':
plt.plot(lap[i],time_nor[i],'xb')
plt.legend()
plt.xlabel('Lap')
plt.ylabel('Time (sec)')
plt.show()
And here is the code to display the safety car legend:
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
for i in range(0,len(info)):
if info[i]=='SC':
plt.axvspan(i+1,i+2,facecolor='yellow',alpha=0.5) #Display when Safety Car is deployed
if info_lec[i]=='P': #Remove time lost during pitstop
time_lec[i]=time_lec[i]-25
if info_nor[i]=='P':
time_nor[i]=time_nor[i]-25
plt.plot(lap,time_lec,'.:r',label='Leclerc',linewidth=1.2)
plt.plot(lap,time_nor,'.:b',label='Norris',linewidth=1.2)
for i in range(0,len(info)): #Displaying the lap where the driver is pitting (to change tires)
if info_lec[i]=='P':
plt.plot(lap[i],time_lec[i],'xr')
if info_nor[i]=='P':
plt.plot(lap[i],time_nor[i],'xb')
sc_patch = mpatches.Patch(color='yellow', alpha=0.5, label='Safety car')
plt.legend(handles=[sc_patch])
plt.xlabel('Lap')
plt.ylabel('Time (sec)')
plt.show()
Note: If I'm adding plt.legend()
just before plt.show()
, we will not see the safety car legend
And here are the two legends I can get even though I would like to have everything at once : We can notice the the marker changed for the pit stop (lap 28) but is not shown in any legend boxes
The objective is to have the 2 legends as one : One legend where there are Leclerc, Norris, Safety Car, Red Flag
Solution
To create a custom legend you need to get the plot objects and use them when defining your legend, as explicited on matplotlib's documentation:
- Explicitly defining the elements in the legend
For full control of which artists have a legend entry, it is possible to pass an iterable of legend artists followed by an iterable of legend labels respectively:
ax.legend([line1, line2, line3], ['label1', 'label2', 'label3'])
Also, you may add the labels when creating the vertical bands.
import matplotlib.pyplot as plt
atl=25 # Average time lost during pitstop
RedFlag_color='#C33A33'
SafetyCar_color='#F9D849'
Ferrari_color='#CA2A1D'
McLaren_color='#F29C38'
lap=[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]
info=['SC', 'SC', 'SC', 'SC', 'SC', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 'RF', 'SC', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
time_lec=[145.323, 141.062, 142.84, 145.489, 136.873, 99.585, 94.848, 92.511, 91.679, 90.706, 90.268, 89.44, 89.089, 88.806, 89.571, 88.137, 87.54, 88.092, 88.526, 87.624, 87.05, 87.21, 86.79, 88.31, 88.054, 87.537, 92.467, 88.853, 84.319, 84.395, 111.855, 131.844, None, 85.394, 81.509, 80.807, 80.439, 80.43, 79.512, 79.561, 79.446, 79.399, 79.237, 79.219, 79.37, 78.938, 79.145, 79.025, 78.818, 78.784, 79.094, 78.739, 79.31, 80.016, 78.97, 78.622, 78.676, 78.689, 78.379, 78.575, 78.461, 78.624]
time_nor=[142.471, 139.843, 147.079, 141.984, 130.516, 104.428, 98.389, 94.898, 93.029, 92.971, 91.482, 91.918, 89.719, 90.113, 88.964, 87.946, 87.101, 87.049, 87.419, 89.988, 88.538, 88.908, 88.592, 89.157, 89.051, 88.315, 92.204, 87.737, 84.987, 83.211, 128.26, 116.233, None, 83.618, 81.8, 80.748, 80.578, 79.946, 79.745, 79.386, 79.591, 79.484, 79.352, 79.388, 79.205, 78.979, 78.984, 79.025, 79.074, 78.838, 78.95, 78.787, 79.053, 78.717, 78.756, 78.653, 78.951, 78.659, 79.342, 78.557, 78.571, 78.259]
info_lec=[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 'P', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
info_nor=[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 'P', None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
for i in range(0,len(info)):
if info[i]=='SC':
plot_SafetyCar = plt.axvspan(
i+2,i+3,facecolor=SafetyCar_color,alpha=0.5,
label='Safety Car') #Display when Safety Car is deployed
if info[i]=='RF':
plot_RedFlag = plt.axvspan(
i+2,i+3,facecolor=RedFlag_color,label='Red Flag')
if info_lec[i]=='P':
time_lec[i]=time_lec[i]-atl
if info_nor[i]=='P':
time_nor[i]=time_nor[i]-atl
plot_Leclerc, = plt.plot(
lap,time_lec,'.:',label='Leclerc',color=Ferrari_color,linewidth=1.2)
plot_McLaren, = plt.plot(
lap,time_nor,'.:',label='Norris',color=McLaren_color,linewidth=1.2)
for i in range(0,len(info)): #Displaying the lap where the driver is pitting (to change tires)
if info_lec[i]=='P':
plt.plot(lap[i],time_lec[i],'x',color=Ferrari_color)
if info_nor[i]=='P':
plt.plot(lap[i],time_nor[i],'x',color=McLaren_color)
plt.legend(handles=[plot_Leclerc,plot_McLaren,plot_SafetyCar,plot_RedFlag])
plt.xlabel('Lap')
plt.ylabel('Time (sec)')
plt.show()
Answered By - wagnifico
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.