How to Remove duplicate labels in subplot legend - python

The following code will generate a legend with duplicated labels. How to remove the duplicated one, so that there is only 1 label1 and 1 label2? One possible approach is to remove the duplicated item in the lines_labels list, but I couldn't figure out the code. Can someone please help? Thanks a lot!
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
ax1.scatter(1,2,label='a',color='black')
ax1.plot(np.array([1, 2]), np.array([1, 2]),color='b',label='xvalues')
ax2.scatter(3,4,label='a',color='black')
ax3.scatter(5,6,label='b',color='red')
ax4.scatter(7,8,label='b',color='red')
lines_labels = [ax.get_legend_handles_labels() for ax in fig.axes]
lines, labels = [sum(lol, []) for lol in zip(*lines_labels)]
fig.legend(lines, labels, scatterpoints = 1)
plt.show()

you could put all labels and lines in a dict and filter only for unique labels like this
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
ax1.scatter(1, 2, label='a', color='black')
ax1.plot(np.array([1, 2]), np.array([1, 2]), color='b', label='xvalues')
ax2.scatter(3, 4, label='a', color='black')
ax3.scatter(5, 6, label='b', color='red')
ax4.scatter(7, 8, label='b', color='red')
lines_labels = [ax.get_legend_handles_labels() for ax in fig.axes]
lines, labels = [sum(lol, []) for lol in zip(*lines_labels)]
# grab unique labels
unique_labels = set(labels)
# assign labels and legends in dict
legend_dict = dict(zip(labels, lines))
# query dict based on unique labels
unique_lines = [legend_dict[x] for x in unique_labels]
fig.legend(unique_lines, unique_labels, scatterpoints=1)
plt.show()

Related

Why can't I change the padding on my GridSpecFromSubplotSpec? [duplicate]

I would like to make a variable (two different) wspace using GridSpec in matplotlib.
I would like to achieve the following:
I'm using the following so far:
gs1 = gridspec.GridSpec(6, 3, width_ratios=[1.5,1,1])
gs1.update(wspace=0.4, hspace=0.3)
ax1 = fig.add_subplot(gs1[0:2,0])
ax2 = fig.add_subplot(gs1[2:4,0])
ax3 = fig.add_subplot(gs1[4:6,0])
ax4 = fig.add_subplot(gs1[0:3,1])
ax5 = fig.add_subplot(gs1[3:6,1])
ax6 = fig.add_subplot(gs1[0:3,2])
ax7 = fig.add_subplot(gs1[3:6,2])
Any idea how to obtain the two different space highlighted in green in my amazing hand drawing ?
Thanks a lot !
Sam
You may use 2 GridSpecs, one which contains one column and 3 rows and one which contains two rows and two colums. You can then let the first extend only to less than half of the figure and start the second at half the figure width. The difference between the left and right parameter will be the spacing.
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
fig = plt.figure()
gs1 = GridSpec(3, 1, right=0.4)
gs2 = GridSpec(2, 2, left=0.5)
ax1 = fig.add_subplot(gs1[0,0])
ax2 = fig.add_subplot(gs1[1,0])
ax3 = fig.add_subplot(gs1[2,0])
ax4 = fig.add_subplot(gs2[0,0])
ax5 = fig.add_subplot(gs2[0,1])
ax6 = fig.add_subplot(gs2[1,0])
ax7 = fig.add_subplot(gs2[1,1])
plt.show()
The same can be achieved with first defining an "outer" gridspec with two columns and placing an inner gridspec into each of them.
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec
fig = plt.figure()
gs = GridSpec(1, 2, width_ratios=[1.5,2], wspace=0.3)
gs1 = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs[0])
gs2 = GridSpecFromSubplotSpec(2, 2, subplot_spec=gs[1])
ax1 = fig.add_subplot(gs1[0,0])
ax2 = fig.add_subplot(gs1[1,0])
ax3 = fig.add_subplot(gs1[2,0])
ax4 = fig.add_subplot(gs2[0,0])
ax5 = fig.add_subplot(gs2[0,1])
ax6 = fig.add_subplot(gs2[1,0])
ax7 = fig.add_subplot(gs2[1,1])
plt.show()

Markers in beginning and end of line plots

I have 5 datasets that have thousands of x and y coordinates grouped by 'frame' that create 5 trajectory plots. I'd like to mark the first and last coordinates for each plot but having difficulty figuring it out. I am using Jupiter Notebook.
mean_pos1 = gr1.mean()
mean_pos2 = gr2.mean()
mean_pos3 = gr3.mean()
mean_pos4 = gr4.mean()
mean_pos5 = gr5.mean()
plt.figure()
xlim=(200, 1500)
ylim=(0, 1200)
ax1 = mean_pos1.plot(x='x', y='y',color='blue',label='Dolphin A'); ax1.set_title('mean trajectory');
ax2 = mean_pos2.plot(x='x', y='y',color='red',label='Dolphin B'); ax2.set_title('mean trajectory');
ax3 = mean_pos3.plot(x='x', y='y',color='green',label='Dolphin C'); ax3.set_title('mean trajectory');
ax4 = mean_pos4.plot(x='x', y='y',color='magenta',label='Dolphin D'); ax4.set_title('mean trajectory');
ax5 = mean_pos5.plot(x='x', y='y',color='cyan',label='Dolphin E'); ax5.set_title('mean trajectory');
ax1.set_xlim(xlim)
ax1.set_ylim(ylim)
ax2.set_xlim(xlim)
ax2.set_ylim(ylim)
ax3.set_xlim(xlim)
ax3.set_ylim(ylim)
ax4.set_xlim(xlim)
ax4.set_ylim(ylim)
ax5.set_xlim(xlim)
ax5.set_ylim(ylim)
plt.show()
the output of them looks like this:
Use the scatter method to plot the markers separately on the same axis by grabbing the first and last elements from your x and y series:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'x': np.random.normal(3,0.2,10), 'y': np.random.normal(5,0.3,10)})
fig, ax = plt.subplots()
df.plot(x='x', y='y', ax=ax)
ax.scatter(df['x'].iloc[0], df['y'].iloc[0], marker='o', color='red')
ax.scatter(df['x'].iloc[-1], df['y'].iloc[-1], marker='o', color='red')
plt.show()

Plot matplotlib histogram legend on separate figure

Given a line plot obtained with ax.plot(), I have the following handy code to plot the legend on a separate figure:
fig, ax = plt.subplots()
ax.plot([0, 2], label='a', linestyle='--')
ax.plot([-1, 1], label='b', linestyle='dotted')
fig = plt.figure(figsize=(30, 4), constrained_layout=True)
fig.legend(ax.lines, [l.get_label() for l in ax.lines],
loc="upper center")
However if I do this with a histogram (using ax.hist()), ax.lines is empty and I cannot get the labels and styles used. Is it possible to do that still ?
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.random.randn(1000, 3)
colors = ['red', 'tan', 'lime']
_,_,patches = ax.hist(x, 10, color=colors, label=colors)
fig = plt.figure(figsize=(30, 4), constrained_layout=True)
fig.legend([p[0] for p in patches], [p[0].get_label() for p in patches],
loc="upper center")
UPDATE as per comment: you can achieve the same using ax.patches instead of patches returned by ax.hist like so:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
x = np.random.randn(1000, 3)
colors = ['red', 'tan', 'lime']
n_bins = 10
ax.hist(x, n_bins, color=colors, label=colors)
fig = plt.figure(figsize=(3, 4), constrained_layout=True)
fig.legend(ax.patches[::n_bins], [p.get_label() for p in ax.patches[::n_bins]], loc="upper center")

Matplotlib: how to remove spacing between a group of subplots

I have a series of pyplot subplots that I've created using a gridspec. They all have an hspace between them, which is fine, except that I would like to keep three of them without any space. Is there a way to do this? Currently, they look like this:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure()
grid_spec = gridspec.GridSpec(nrows=10, ncols=10)
grid_spec.update(hspace=1.5)
ax1 = plt.subplot(grid_spec[0:4, :])
ax2 = plt.subplot(grid_spec[4:7, :], sharex=ax1)
# I would like to group the next 3 together
# so that they are stacked top to bottom and side by side
ax3 = plt.subplot(grid_spec[7:8, :5])
ax4 = plt.subplot(grid_spec[8:, :5], sharex=ax3)
ax5 = plt.subplot(grid_spec[8:, 5:6], sharey=ax4)
plt.show()
I would like them to be arranged like this so I can plot the following 2-D KDE diagram and have the relevant 1-D diagrams above and to the right (roughly displaying this sort of data crudely drawn in paint):
I appreciate any help with this one. Can't seem to find documentation on this sort of thing. Thanks!
You can use mpl_toolkits.axes_grid1.make_axes_locatable to subdivide the area of a subplot of a 3 x 2 grid.
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
fig = plt.figure()
gs = fig.add_gridspec(nrows=3, ncols=2, hspace=.5,
height_ratios=[4, 3, 3], width_ratios=[7, 4])
ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, :], sharex=ax1)
ax3 = fig.add_subplot(gs[2, 0])
div = make_axes_locatable(ax3)
ax4 = div.append_axes("top", "40%", pad=0.2, sharex=ax3)
ax5 = div.append_axes("right", "25%", pad=0.2, sharey=ax3)
ax4.tick_params(labelbottom=False)
ax5.tick_params(labelleft=False)
plt.show()
Also, you can create a subgridspec, like
import matplotlib.pyplot as plt
from matplotlib import gridspec
fig = plt.figure()
gs = gridspec.GridSpec(nrows=3, ncols=2, hspace=.5,
height_ratios=[4, 3, 3], width_ratios=[7, 4])
ax1 = fig.add_subplot(gs[0, :])
ax2 = fig.add_subplot(gs[1, :], sharex=ax1)
sub_gs = gridspec.GridSpecFromSubplotSpec(2,2, subplot_spec=gs[2,0], hspace=0.3, wspace=0.1,
height_ratios=[1,3], width_ratios=[3,1])
ax3 = fig.add_subplot(sub_gs[1,0])
ax4 = fig.add_subplot(sub_gs[0,0], sharex=ax3)
ax5 = fig.add_subplot(sub_gs[1,1], sharey=ax3)
ax4.tick_params(labelbottom=False)
ax5.tick_params(labelleft=False)
plt.show()
In both cases you will probably want to fine tune the parameters a bit. In general, the matplotlib gridspec tutorial gives a nice overview with many examples on this matter.

Secondary axis with twinx(): how to add to legend?

I have a plot with two y-axes, using twinx(). I also give labels to the lines, and want to show them with legend(), but I only succeed to get the labels of one axis in the legend:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(time, Swdown, '-', label = 'Swdown')
ax.plot(time, Rn, '-', label = 'Rn')
ax2 = ax.twinx()
ax2.plot(time, temp, '-r', label = 'temp')
ax.legend(loc=0)
ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()
So I only get the labels of the first axis in the legend, and not the label 'temp' of the second axis. How could I add this third label to the legend?
You can easily add a second legend by adding the line:
ax2.legend(loc=0)
You'll get this:
But if you want all labels on one legend then you should do something like this:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')
time = np.arange(10)
temp = np.random.random(10)*30
Swdown = np.random.random(10)*100-10
Rn = np.random.random(10)*100-10
fig = plt.figure()
ax = fig.add_subplot(111)
lns1 = ax.plot(time, Swdown, '-', label = 'Swdown')
lns2 = ax.plot(time, Rn, '-', label = 'Rn')
ax2 = ax.twinx()
lns3 = ax2.plot(time, temp, '-r', label = 'temp')
# added these three lines
lns = lns1+lns2+lns3
labs = [l.get_label() for l in lns]
ax.legend(lns, labs, loc=0)
ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()
Which will give you this:
I'm not sure if this functionality is new, but you can also use the get_legend_handles_labels() method rather than keeping track of lines and labels yourself:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')
pi = np.pi
# fake data
time = np.linspace (0, 25, 50)
temp = 50 / np.sqrt (2 * pi * 3**2) \
* np.exp (-((time - 13)**2 / (3**2))**2) + 15
Swdown = 400 / np.sqrt (2 * pi * 3**2) * np.exp (-((time - 13)**2 / (3**2))**2)
Rn = Swdown - 10
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(time, Swdown, '-', label = 'Swdown')
ax.plot(time, Rn, '-', label = 'Rn')
ax2 = ax.twinx()
ax2.plot(time, temp, '-r', label = 'temp')
# ask matplotlib for the plotted objects and their labels
lines, labels = ax.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc=0)
ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()
From matplotlib version 2.1 onwards, you may use a figure legend. Instead of ax.legend(), which produces a legend with the handles from the axes ax, one can create a figure legend
fig.legend(loc="upper right")
which will gather all handles from all subplots in the figure. Since it is a figure legend, it will be placed at the corner of the figure, and the loc argument is relative to the figure.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10)
y = np.linspace(0,10)
z = np.sin(x/3)**2*98
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,y, '-', label = 'Quantity 1')
ax2 = ax.twinx()
ax2.plot(x,z, '-r', label = 'Quantity 2')
fig.legend(loc="upper right")
ax.set_xlabel("x [units]")
ax.set_ylabel(r"Quantity 1")
ax2.set_ylabel(r"Quantity 2")
plt.show()
In order to place the legend back into the axes, one would supply a bbox_to_anchor and a bbox_transform. The latter would be the axes transform of the axes the legend should reside in. The former may be the coordinates of the edge defined by loc given in axes coordinates.
fig.legend(loc="upper right", bbox_to_anchor=(1,1), bbox_transform=ax.transAxes)
You can easily get what you want by adding the line in ax:
ax.plot([], [], '-r', label = 'temp')
or
ax.plot(np.nan, '-r', label = 'temp')
This would plot nothing but add a label to legend of ax.
I think this is a much easier way.
It's not necessary to track lines automatically when you have only a few lines in the second axes, as fixing by hand like above would be quite easy. Anyway, it depends on what you need.
The whole code is as below:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')
time = np.arange(22.)
temp = 20*np.random.rand(22)
Swdown = 10*np.random.randn(22)+40
Rn = 40*np.random.rand(22)
fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()
#---------- look at below -----------
ax.plot(time, Swdown, '-', label = 'Swdown')
ax.plot(time, Rn, '-', label = 'Rn')
ax2.plot(time, temp, '-r') # The true line in ax2
ax.plot(np.nan, '-r', label = 'temp') # Make an agent in ax
ax.legend(loc=0)
#---------------done-----------------
ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()
The plot is as below:
Update: add a better version:
ax.plot(np.nan, '-r', label = 'temp')
This will do nothing while plot(0, 0) may change the axis range.
One extra example for scatter
ax.scatter([], [], s=100, label = 'temp') # Make an agent in ax
ax2.scatter(time, temp, s=10) # The true scatter in ax2
ax.legend(loc=1, framealpha=1)
Preparation
import numpy as np
from matplotlib import pyplot as plt
fig, ax1 = plt.subplots( figsize=(15,6) )
Y1, Y2 = np.random.random((2,100))
ax2 = ax1.twinx()
Content
I'm surprised it did not show up so far but the simplest way is to either collect them manually into one of the axes objs (that lie on top of each other)
l1 = ax1.plot( range(len(Y1)), Y1, label='Label 1' )
l2 = ax2.plot( range(len(Y2)), Y2, label='Label 2', color='orange' )
ax1.legend( handles=l1+l2 )
or have them collected automatically into the surrounding figure by fig.legend() and fiddle around with the the bbox_to_anchor parameter:
ax1.plot( range(len(Y1)), Y1, label='Label 1' )
ax2.plot( range(len(Y2)), Y2, label='Label 2', color='orange' )
fig.legend( bbox_to_anchor=(.97, .97) )
Finalization
fig.tight_layout()
fig.savefig('stackoverflow.png', bbox_inches='tight')
A quick hack that may suit your needs..
Take off the frame of the box and manually position the two legends next to each other. Something like this..
ax1.legend(loc = (.75,.1), frameon = False)
ax2.legend( loc = (.75, .05), frameon = False)
Where the loc tuple is left-to-right and bottom-to-top percentages that represent the location in the chart.
I found an following official matplotlib example that uses host_subplot to display multiple y-axes and all the different labels in one legend. No workaround necessary. Best solution I found so far.
http://matplotlib.org/examples/axes_grid/demo_parasite_axes2.html
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
import matplotlib.pyplot as plt
host = host_subplot(111, axes_class=AA.Axes)
plt.subplots_adjust(right=0.75)
par1 = host.twinx()
par2 = host.twinx()
offset = 60
new_fixed_axis = par2.get_grid_helper().new_fixed_axis
par2.axis["right"] = new_fixed_axis(loc="right",
axes=par2,
offset=(offset, 0))
par2.axis["right"].toggle(all=True)
host.set_xlim(0, 2)
host.set_ylim(0, 2)
host.set_xlabel("Distance")
host.set_ylabel("Density")
par1.set_ylabel("Temperature")
par2.set_ylabel("Velocity")
p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density")
p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature")
p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity")
par1.set_ylim(0, 4)
par2.set_ylim(1, 65)
host.legend()
plt.draw()
plt.show()
If you are using Seaborn you can do this:
g = sns.barplot('arguments blah blah')
g2 = sns.lineplot('arguments blah blah')
h1,l1 = g.get_legend_handles_labels()
h2,l2 = g2.get_legend_handles_labels()
#Merging two legends
g.legend(h1+h2, l1+l2, title_fontsize='10')
#removes the second legend
g2.get_legend().remove()
As provided in the example from matplotlib.org, a clean way to implement a single legend from multiple axes is with plot handles:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
fig.subplots_adjust(right=0.75)
twin1 = ax.twinx()
twin2 = ax.twinx()
# Offset the right spine of twin2. The ticks and label have already been
# placed on the right by twinx above.
twin2.spines.right.set_position(("axes", 1.2))
p1, = ax.plot([0, 1, 2], [0, 1, 2], "b-", label="Density")
p2, = twin1.plot([0, 1, 2], [0, 3, 2], "r-", label="Temperature")
p3, = twin2.plot([0, 1, 2], [50, 30, 15], "g-", label="Velocity")
ax.set_xlim(0, 2)
ax.set_ylim(0, 2)
twin1.set_ylim(0, 4)
twin2.set_ylim(1, 65)
ax.set_xlabel("Distance")
ax.set_ylabel("Density")
twin1.set_ylabel("Temperature")
twin2.set_ylabel("Velocity")
ax.yaxis.label.set_color(p1.get_color())
twin1.yaxis.label.set_color(p2.get_color())
twin2.yaxis.label.set_color(p3.get_color())
tkw = dict(size=4, width=1.5)
ax.tick_params(axis='y', colors=p1.get_color(), **tkw)
twin1.tick_params(axis='y', colors=p2.get_color(), **tkw)
twin2.tick_params(axis='y', colors=p3.get_color(), **tkw)
ax.tick_params(axis='x', **tkw)
ax.legend(handles=[p1, p2, p3])
plt.show()
Here is another way to do this:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rc
rc('mathtext', default='regular')
fig = plt.figure()
ax = fig.add_subplot(111)
pl_1, = ax.plot(time, Swdown, '-')
label_1 = 'Swdown'
pl_2, = ax.plot(time, Rn, '-')
label_2 = 'Rn'
ax2 = ax.twinx()
pl_3, = ax2.plot(time, temp, '-r')
label_3 = 'temp'
ax.legend([pl[enter image description here][1]_1, pl_2, pl_3], [label_1, label_2, label_3], loc=0)
ax.grid()
ax.set_xlabel("Time (h)")
ax.set_ylabel(r"Radiation ($MJ\,m^{-2}\,d^{-1}$)")
ax2.set_ylabel(r"Temperature ($^\circ$C)")
ax2.set_ylim(0, 35)
ax.set_ylim(-20,100)
plt.show()
enter image description here
The solutions proposed so far have one or two inconvenients:
Handles needs to be collected individually when plotting, e.g. lns1 = ax.plot(time, Swdown, '-', label = 'Swdown'). There is a risk of forgetting handles when updating the code.
Legend is drawn for the whole figure, not by subplot, which is likely a no-go if you have multiple subplots.
This new solution takes advantage of Axes.get_legend_handles_labels() to collect existing handles and labels for the main axis and for the twin axis.
Collecting handles and labels automatically
This numpy operation will scan all axes which share the same subplot area than ax, including ax and return merged handles and labels:
hl = np.hstack([axis.get_legend_handles_labels()
for axis in ax.figure.axes
if axis.bbox.bounds == ax.bbox.bounds])
It can be used to feed legend() arguments this way:
import numpy as np
import matplotlib.pyplot as plt
t = np.arange(1, 200)
signals = [np.exp(-t/20) * np.cos(t*k) for k in (1, 2)]
fig, axes = plt.subplots(nrows=2, figsize=(10, 3), layout='constrained')
axes = axes.flatten()
for i, (ax, signal) in enumerate(zip(axes, signals)):
# Plot as usual, no change to the code
ax.plot(t, signal, label=f'plotted on axes[{i}]', c='C0', lw=9, alpha=0.3)
ax2 = ax.twinx()
ax2.plot(t, signal, label=f'plotted on axes[{i}].twinx()', c='C1')
# The only specificity of the code is when plotting the legend
h, l = np.hstack([axis.get_legend_handles_labels()
for axis in ax.figure.axes
if axis.bbox.bounds == ax.bbox.bounds]).tolist()
ax2.legend(handles=h, labels=l, loc='upper right')

Categories

Resources