Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib: subtitle in the wrong position and legend not visible

I have five lists which I intend to plot in two separate subplots. In subplot 1 I want list 1, 2, 3 and 4; in subplot 2 I want list 4 and 5. These are the lists and the event_index used to set the x label.

event_index=['event 1','event 2','event 3','event 4','event 5','event 6','event 7','event 8','event 9','event 10']
list1 = [0.7,0.8,0.8,0.9,0.8,0.7,0.6,0.9,1.0,0.9]
list2 = [0.2,0.3,0.1,0.0,0.2,0.1,0.3,0.1,0.2,0.1]
list3 = [0.4,0.6,0.4,0.5,0.4,0.5,0.6,0.4,0.5,0.4]
list4 = [78,87,77,65,89,98,74,94,85,73]
list5 = [16,44,14,55,34,36,76,54,43,32]

To produce the two subplots I use the following code:

fig = plt.figure() #Creates a new figure
ax1 = fig.add_subplot(211) #First subplot: list 1,2,3, and 4
ax2 = ax1.twinx() #Creates a twin y-axis for plotting the values of list 4
line1 = ax1.plot(list1,'bo-',label='list1') #Plotting list1
line2 = ax1.plot(list2,'go-',label='list2') #Plotting list2
line3 = ax1.plot(list3,'ro-',label='list3') #Plotting list3
line4 = ax2.plot(list4,'yo-',label='list4') #Plotting list4
ax1.set_ylim(0,1)
ax1.set_xlim(1, len(event_index)+1)
ax1.set_ylabel('Some values',fontsize=12)
ax2.set_ylabel('% values',fontsize=12)
ax2.set_ylim(0,100)
ax2.set_xlim(1, len(event_index)+1)
ax3 = fig.add_subplot(212) #Second subplot: list 4 and 5
ax3.set_xlim(1, len(event_index)+1)
ax3.set_ylabel('% values',fontsize=12)
#Plotting Footprint % and Critical Cells %
ax3.plot(list4,'yo-',label='list4')
line5 = ax3.plot(list5,'mo-',label='list5')
#Assigning labels
lines = line1+line2+line3+line4+line5
labels = [l.get_label() for l in lines]
ax3.legend(lines, labels, loc=(0,-0.4), ncol=5) #The legend location. All five series are in the same legend.
ax3.set_xlabel('events')
title_string=('Some trends')
subtitle_string=('Upper panel: list 1, 2, 3, and 4 | Lower panel: list 4 and 5')
plt.suptitle(title_string, y=0.99, fontsize=17)
plt.title(subtitle_string, fontsize=8)
fig.tight_layout()
plt.show()

What I get is this: enter image description here

A few problems:

  1. The subtitle is not above the first subplot but above the second
  2. I cannot see/read the legend, which I want to be centered, but below the x labels of subplot 2
  3. All my lists have len=10, but only 9 values are plotted
  4. Possibly, I want to get rid of the y-axis ticks in the second subplot
  5. I would like the chart title, Some trends, not to be "glued" to the first subplot

How could I improve my chart? Thanks!

like image 293
FaCoffee Avatar asked Jan 08 '23 04:01

FaCoffee


2 Answers

  1. Plot the subtitle using ax1.set_title, not plt.title (as that will plot a title on the last active subplot)

  2. I showed you in your last question how to make room for the legend at the bottom. You need to fig.subplots_adjust(bottom=0.3) (you might need to adjust the 0.3)

  3. you only have 9 points because you are cutting out the first by setting xlim to (1,len(list)+1), since python indexes from 0, not 1. Instead, create a list to plot as your x values:

    x = range(1,len(list1)+1)
    ax1.plot(x, list1)
    
  4. Use ax3.yaxis.set_ticks_position('left') to only plot the ticks on the left and turn them off on the right

  5. You can move this increasing the y argument, e.g.

    plt.suptitle(title_string, y=1.05, fontsize=17)
    
like image 196
tmdavison Avatar answered Jan 21 '23 01:01

tmdavison


  1. You can manually set the position of the suptitle as described here: http://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure.suptitle Just use it like this with x and y being relative coordinates of your plot (from 0 to 1):

    suptitle("Here goes the title", x=0.5, y=0.95)
    
  2. You can set the legend position with as described here: https://stackoverflow.com/a/4701285/5528308 Try this as suggested by user Joe Kington

    # Shrink current axis's height by 10% on the bottom
    box = ax.get_position()
    ax.set_position([box.x0, box.y0 + box.height * 0.1,
             box.width, box.height * 0.9])
    
    # Put a legend below current axis
    ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
          fancybox=True, shadow=True, ncol=5)
    
  3. Your plots only show 9 values, because you x-axes start at 1 but Python's iteration starts at 0. Since you give no x values in your plot, Python plots from 0 to 9 but you limited the axes from 1 to 10. Do this:

    x_vals = np.linspace(1,10,10)
    line1 = ax1.plot(x_vals, list1,'bo-',label='list1')
    

    and repeat for the other plots.

  4. What do you mean by grid? Usually grid refers to the gridlines, which you do not have. If you mean the ticks you can remove them with ax2.get_yaxis().set_ticks([])

  5. Try using plt.gcf().tight_layout(). This will arrange your plot with proper whitespace everywhere in most cases.

like image 35
Ian Avatar answered Jan 21 '23 03:01

Ian