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

huangapple go评论63阅读模式
英文:

How to reposition Figure legends into subfigures

问题

我是新手,尝试在Jupyter Notebook中使用Matplotlib和Seaborn库绘制水平的两个子图,使用示例数据。两个子图显示正常,但两个图例重叠在最右边。我无法找到将第一个子图的图例移到左边的方法。非常感谢任何建议!

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

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()
英文:

I am new to this, trying to plot 2 subfigures horizontal with sample data using Matplotlib and Seaborn library in Jupyter Notebook, the 2 sub-charts come out alright, but the 2 legends overlap each other on the far right hand. I couldn't figure out a way to move legend of the 1st sub-figure to the left. Any suggestions are greatly appreciated!

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

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()

答案1

得分: 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]);

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

(我知道上面的代码和图与你想要的无关; 但是,它导入了某些内容或设置了某些内容,我认为它是你需要的代码(下面的内容)的一部分。需要与不相关的代码和图表是为什么我说它非常笨拙。 但如果没有它,我无法让它正常工作,而且当我将它放在那里时,它运行得相当顺利,所以我分享出来。也许它会有助于找出更干净的解决方案。)

在下一个单元格中,放置这个代码的变体:

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) # 不需要显示“day”图例,因此使用此方法
sf2.legend(legend.legendHandles, [t.get_text() for t in legend.texts])
f.figure

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

我没有看到为什么你需要显示“day”图例,因为左侧面板的绘图显然已经处理了它,所以我使用pop方法将其删除。

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

英文:

This is super clunky, probably because handling legends in the seaborn.objects interface is a work in progress but this seems to get close to what you want, I think?

In a first cell use an example from the posted solution there.

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]);

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

(I know that code and plot above has nothing to do with what you want; however, it imports something or sets up something that I couldn't get the code I thought should be all you need (below) to do on it's own. Needing that unrelated code and plot is why I say it's super clunky. But I couldn't get it to work without it, and it worked fairly well when I had it there and so I'm sharing. Maybe it will factor into figuring out a cleaner solution.)

In the next cell, put this variation of your code:

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

Run that and it should look a little better without the two legends overlapping on the far right side.

I didn't see why you need the 'day' legend showing because that is clearly handled in the plots on the left panel , and so I used the pop method to remove it.

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

答案2

得分: 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()
)

# 从主图中删除图例
l2 = f.legends.pop(1)
l1 = f.legends.pop(0)

# 将图例属性添加到适当的子图中
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

希望这能帮助您理解代码部分。

英文:

Slight change in how the legends are assigned to each subfigure

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

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

huangapple
  • 本文由 发表于 2023年4月4日 05:09:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75923791.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定