4

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!

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
FaCoffee
  • 7,609
  • 28
  • 99
  • 174
  • 1
    Isn't it too much? They all relate to the same topic, which is how to properly display a 2-subplot chart. Also, some of the separate questions could be labeled as `duplicate`, and future readers might incur in the same problem... – FaCoffee Nov 13 '15 at 12:32
  • 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) – tmdavison Nov 13 '15 at 12:36
  • 2
    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 – tmdavison Nov 13 '15 at 12:37

2 Answers2

6
  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)
    
tmdavison
  • 64,360
  • 12
  • 187
  • 165
  • Yes, sorry. Point 4 refers to the `y-axis` ticks on the lower subgraph. I will reword the question itself. – FaCoffee Nov 13 '15 at 12:42
  • on both sides, or just the left? – tmdavison Nov 13 '15 at 12:43
  • Yes, sorry. On the right side, if possible. If not, no worries. – FaCoffee Nov 13 '15 at 12:44
  • Thanks. Your answer #1: if I call `ax1.title(subtitle_string, fontsize=8)`, I get `TypeError: 'Text' object is not callable` pointing right to the line where `ax1.title()` is. – FaCoffee Nov 13 '15 at 12:47
  • 1
    ah yes, that was meant to be `ax1.set_title`. Edited again – tmdavison Nov 13 '15 at 12:49
  • It works. I imagine I can move the subtitle wherever I want by setting `y=0.98`, for instance. The problem is that if I leave it this way, it gets "glued" to the main title, which has `y=1.00`. But if the main title has `y=1.05`, it goes out of view, so I cannot find a balance here... – FaCoffee Nov 13 '15 at 12:55
  • Is there any way of "moving" everything down to have titles and charts more spaced out? – FaCoffee Nov 13 '15 at 13:02
  • 1
    in the same way you make space at the bottom, you can make space at the top, e.g. `fig.subplots_adjust(top=0.85,bottom=0.2)` – tmdavison Nov 13 '15 at 13:06
3
  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.

Community
  • 1
  • 1
Ian
  • 1,688
  • 18
  • 35