如何将图形图例重新定位到子图形中

问题描述 投票:0回答:2

我对此很陌生,尝试使用 Jupyter Notebook 中的 Matplotlib 和 Seaborn 库用示例数据水平绘制 2 个子图,这 2 个子图显示正常,但 2 个图例在最右侧相互重叠。我无法找到将第一个子图的图例移至左侧的方法。非常感谢任何建议!

screenshot

import matplotlib as mpl
tips = sns.load_dataset("tips")

f = mpl.figure.Figure(figsize=(8, 2), dpi=100)
sf1, sf2 = f.subfigures(1, 2)

(
    so.Plot(tips, "total_bill", "tip", color="day")
    .facet(col="day")
    .add(so.Dot(color="#aabc"), col=None, color=None)
    .add(so.Dot())
).on(sf1).plot()

(
    so.Plot(tips, "total_bill", "tip")
    .add(so.Dot(color="#aabc"))
    .add(so.Dot(), data=tips.query("size == 1"), color="time")
).on(sf2).plot()
python matplotlib seaborn legend seaborn-objects
2个回答
2
投票

这非常笨重,可能是因为在 seaborn.objects 接口中处理图例是一项正在进行的工作,但这似乎接近你想要的,我认为?

在第一个单元格中使用发布的解决方案中的示例那里

import seaborn as sns
import matplotlib.pyplot as plt
import seaborn.objects as so
tips = sns.load_dataset("tips")
f, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)

(
     so.Plot(tips, x='total_bill', y='tip', color='day')
     .add(so.Dot(pointsize=2))
     .add(so.Line(color='k'), so.PolyFit(order=1), color=None)
     .on(ax1)
     .plot()
)
legend = f.legends.pop(0)
ax1.legend(legend.legendHandles, [t.get_text() for t in legend.texts]);

enter image description here

(我知道上面的代码和绘图与你想要的无关;但是,它导入了一些东西或设置了一些我无法获得的东西,我认为应该是你需要(下面)自己做的所有事情需要不相关的代码和情节是我说它超级笨重的原因。但是如果没有它我就无法让它工作,而且当我有它时它工作得相当好,所以我分享它。找出更清洁的解决方案。)

在下一个单元格中,输入以下代码变体:

import seaborn as sns
import seaborn.objects as so
import matplotlib as mpl
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")

f = mpl.figure.Figure(figsize=(8, 2), dpi=100)
sf1, sf2 = f.subfigures(1, 2)

(
    so.Plot(tips, "total_bill", "tip", color="day")
    .facet(col="day")
    .add(so.Dot(color="#aabc"), col=None, color=None)
    .add(so.Dot())
    .on(sf1)
    .plot()
)

(
    so.Plot(tips, "total_bill", "tip")
    .add(so.Dot(color="#aabc"))
    .add(so.Dot(), data=tips.query("size == 1"), color="time")
    .on(sf2)
    .plot()
)
legend = f.legends.pop(1)
f.legends.pop(0) # don't need the 'day' legend showing, so use this
sf2.legend(legend.legendHandles, [t.get_text() for t in legend.texts])
f.figure

运行它,它看起来应该会好一点,两个图例不会在最右侧重叠。

我不明白为什么你需要显示“日”图例,因为这在左侧面板的图中已经清楚地处理了,所以我使用

pop
方法将其删除。

enter image description here


0
投票

图例分配给每个子图的方式略有变化

import seaborn as sns
import seaborn.objects as so
import matplotlib as mpl
import matplotlib.pyplot as plt

tips = sns.load_dataset("tips")

f = mpl.figure.Figure(figsize=(8, 2), dpi=100)
sf1, sf2 = f.subfigures(1, 2)

(
    so.Plot(tips, "total_bill", "tip", color="day")
    .facet(col="day")
    .add(so.Dot(color="#aabc"), col=None, color=None)
    .add(so.Dot())
    .on(sf1)
    .plot()
)

(
    so.Plot(tips, "total_bill", "tip")
    .add(so.Dot(color="#aabc"))
    .add(so.Dot(), data=tips.query("size == 1"), color="time")
    .on(sf2)
    .plot()
)

# remove the legends from the primary figure
l2 = f.legends.pop(1)
l1 = f.legends.pop(0)

# add the legend properties to the appropriate subfigure
sf1.legend(l1.legend_handles, [t.get_text() for t in l1.texts])
sf2.legend(l2.legend_handles, [t.get_text() for t in l2.texts])

f.figure

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.