proplot-dev / proplot

🎨 A succinct matplotlib wrapper for making beautiful, publication-quality graphics
https://proplot.readthedocs.io
MIT License
1.07k stars 96 forks source link

When used with seaborn, legend draws error: two legend label boxes appear. #358

Open moulai opened 2 years ago

moulai commented 2 years ago

Description

I was using propplot as the layout tool and seaborn as the plotting tool. Everything was fine until I used ax.legend(loc='b') to add a label box below the plot. Two tab boxes appeared! One is drawn by seaborn itself, and the other is drawn by propplot. I tried adding legend=False to sns.lineplot(), however, this makes proplot unable to get all the legend information (because seaborn will not add the automatically generated legend information except the label to the handler). How to solve this problem please? I can turn off the legend of proplot, but then I can't adjust the position of the legend box!

Steps to reproduce

fig, axs = pplt.subplots(ncols = 1, nrows = 2, refaspect=2, refwidth=5, sharey=False)
axs.format(abc='a', abcloc='ul')
sns.lineplot(ax=axs[0], data=global_mean, x="year", y="LAI", hue="Dataset", legend=False)
axs[0].format(ylabel='Global Mean LAI ($\mathregular{m^2/m^2}$)')

sns.lineplot(ax=axs[1], data=global_annomaly, x="year", y="LAI", hue="Dataset")
sns.lineplot(ax=axs[1], data=global_annomaly, x="year", y="LAI", color="black", linewidth=2.2, label="Multi-dataset Mean")
axs[1].format(ylabel="Global LAI Anomaly ($\mathregular{m^2/m^2}$)")
axs[1].legend(loc='b')
fig.show()

Expected behavior: Only one legend box on the bottom of the plot.

Actual behavior:

image

Another Example: Adding legend=False to sns.lineplot()

fig, axs = pplt.subplots(ncols = 1, nrows = 2, refaspect=2, refwidth=5, sharey=False)
axs.format(abc='a', abcloc='ul')
sns.lineplot(ax=axs[0], data=global_mean, x="year", y="LAI", hue="Dataset", legend=False)
axs[0].format(ylabel='Global Mean LAI ($\mathregular{m^2/m^2}$)')

sns.lineplot(ax=axs[1], data=global_annomaly, x="year", y="LAI", hue="Dataset", legend=False)
sns.lineplot(ax=axs[1], data=global_annomaly, x="year", y="LAI", color="black", linewidth=2.2, label="Multi-dataset Mean", legend=False)
axs[1].format(ylabel="Global LAI Anomaly ($\mathregular{m^2/m^2}$)")
axs[1].legend(loc='b')
fig.show()
image

Proplot version

Paste the results of import matplotlib; print(matplotlib.__version__); import proplot; print(proplot.version)here. 3.4.3 0.9.5

moulai commented 2 years ago

I have found a solution though the problem in proplot is still yet to be settled. Firstly, I plot only by seaborn with legend=True. Secondly, I get the legend handles by h, l = g.get_legend_handles_labels(). Thirdly, I plot with proplot with legend=False for seaborn (so that seaborn will not draw another legend). Finally, I add the legend by proplot using fig.legend(handles=h, labels=l) Every thing works fine now except I need to plot with seaborn twice (the first time is only for getting the legend handles).

image

I think this problem occurs because proplot rewrites the legend part in matplotlib so that the figure can have multiple legends.