0

The basic design I'm looking for is that I have two scatterplots side by side to each other, and then I wanted to create one legend underneath both subplots that spans both of them. This is a rough sketch:

enter image description here

I'm able to make the plots no problem, but I'm having a hard time getting the legend to do what I want. Here's a sample of the code I have which makes the two scatter plots (I have more data points than this, but for space, I'm just including a few):

import numpy as np
from numpy import array
import matplotlib.pyplot as plt

x = [5,10,20,30]

med1 = [9.35,15.525,26.1,48.275]
med2 = [8.75,14.025,23.95,41.025] 

iqr1 = [13.5125,19.95,38.175,69.9] 
iqr2 = [12.05,19.075,35.075,62.875]

plt.subplot(121)
plt.scatter(x, med1, color='red', alpha=0.5, label='Red stuff')
plt.scatter(x, med2, color='blue', alpha=0.5, label='Blue stuff')
plt.xlim([0,35])
plt.ylim([0,75])
plt.xlabel('Channel Area')
plt.ylabel('Median')

plt.subplot(122)
plt.scatter(x, iqr1, color='red', alpha=0.5, label='More Red Stuff')
plt.scatter(x, iqr2, color='blue', alpha=0.5, label = 'More Blue Stuff')
plt.xlim([0,35])
plt.ylim([0,75])
plt.xlabel('Channel Area')
plt.ylabel('IQR')

What's the best way to make the legend appear as in the figure above?

Brenton
  • 435
  • 2
  • 5
  • 14

2 Answers2

1

You want to use figlegend (demo)

figlegend( (line1, line2, line3), ('label1', 'label2', 'label3'), 'upper right' )

Also look at the answer from this question How to position and align a matplotlib figure legend?

Community
  • 1
  • 1
af3ld
  • 782
  • 8
  • 30
1

Borrowing code from matplotlib - Legend with multiple axes with errorbar object and How to put the legend out of the plot you can do this using these commands:

#Get the lengend handles and labels h1, l1 = ax1.get_legend_handles_labels() h2, l2 = ax2.get_legend_handles_labels()

#Shrink the subplots to make room for the legend
box = ax1.get_position()
ax1.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 0.9])
box = ax2.get_position()
ax2.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 0.9])
#Make the legend
ax1.legend(h1+h2, l1+l2,  bbox_to_anchor=(0,-.05, 2.2,-0.15), loc=9,
           ncol=4)

Where ax1 and ax2 are the axes for the subplots

In your example you can implement like this:

import matplotlib.pyplot as plt
plt.style.use('ggplot')

x = [5,10,20,30]

med1 = [9.35,15.525,26.1,48.275]
med2 = [8.75,14.025,23.95,41.025] 

iqr1 = [13.5125,19.95,38.175,69.9] 
iqr2 = [12.05,19.075,35.075,62.875]

ax1 = plt.subplot(121)
plt.scatter(x, med1, marker='^',color='black', alpha=0.5, label='Triangle!')
plt.scatter(x, med2, color='blue', alpha=0.5, label='Blue Dot')
plt.xlim([0,35])
plt.ylim([0,75])
plt.xlabel('Channel Area')
plt.ylabel('Median')
# ax1 = plt.gca()

ax2 = plt.subplot(122)
plt.scatter(x, iqr1, color='red', alpha=0.5, label='Red Dot')
plt.scatter(x, iqr2, marker='D',color='blue', alpha=0.5, label = 'Diamonds')
plt.xlim([0,35])
plt.ylim([0,75])
plt.xlabel('Channel Area')
plt.ylabel('IQR')
# ax2=plt.gca()

plt.tight_layout() # No overlap of subplots

#Get the lengend handles and labels
h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()

#Shrink the subplots to make room for the legend
box = ax1.get_position()
ax1.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 0.9])
box = ax2.get_position()
ax2.set_position([box.x0, box.y0 + box.height * 0.1,
                 box.width, box.height * 0.9])
#Make the legend
ax1.legend(h1+h2, l1+l2,  bbox_to_anchor=(0,-.05, 2.2,-0.15), loc=9,
           ncol=4)
plt.show()

You can play around with the bbox,ncol, and mode="expand", borderaxespad=0. See http://matplotlib.org/users/legend_guide.html#legend-location for more. The code above should produce this plot:

enter image description here

Community
  • 1
  • 1
Ianhi
  • 2,864
  • 1
  • 25
  • 24
  • This looks really nice! For learning purposes, could you tell me what this part of the code does with ax1.legen: h1+h2, l1+l2, bbox_to_anchor=(0,-.05, 2.2,-0.15), and loc=9? I'm not sure what effect these have on the legend so I"m curious as to what they do – Brenton Jul 16 '16 at 18:25