【问题标题】:Move legend outside figure in seaborn tsplot在seaborn tsplot中将图例移到图外
【发布时间】:2015-08-10 00:39:42
【问题描述】:

我想使用seaborn.tsplot 创建一个时间序列图,就像在this example from tsplot documentation 中一样,但是图例移到了右侧,在图之外。

根据seaborn's timeseries.py 中的第 339-340 行,seaborn.tsplot 目前似乎不允许直接控制图例放置:

    if legend:
        ax.legend(loc=0, title=legend_name)

是否有 matplotlib 解决方法? 我正在使用 seaborn 0.6-dev。

【问题讨论】:

标签: python matplotlib seaborn


【解决方案1】:

确实,seaborn 到目前为止还不能很好地处理图例。您可以使用plt.legend()直接通过matplotlib控制图例属性,按照Matplotlib Legend Guide

请注意,在 Seaborn 0.10.0 中,tsplot 已被删除,您可以使用 lineplot 而不是 tsplot 复制(如果您愿意,使用不同的估计值)图。

片段

import matplotlib.pyplot as plt
import seaborn as sns

sns.set(style="darkgrid")

# Load the long-form example gammas dataset
gammas = sns.load_dataset("gammas")

# Plot the response with standard error
sns.lineplot(data=gammas, x="timepoint", y="BOLD signal", hue="ROI")

# Put the legend out of the figure
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

输出

【讨论】:

  • 最后一行是解决方案。它也适用于我的条形图。
  • 似乎bbox_to_anchor=(1.05, 1) 覆盖了loc=2,所以你可以直接删除loc。还是我错过了什么?
  • 这放了两个图例
  • @JemshitIskenderov 你的 seaborn 和 matplotlib 版本是什么?
  • 在某些情况下,将图例移到绘图之外需要添加“plt.tight_layout()”以完全包含图例。
【解决方案2】:

Sergey 的回答对我使用 seaborn.tsplot 非常有用,但我无法让它为 seaborn.lmplot 工作,所以我更深入地研究并找到了另一个解决方案:

例子:

import seaborn as sns
import pandas as pd

# load data
df = pd.DataFrame.from_csv('mydata.csv')

# create with hue but without legend
g = sns.lmplot(x="x_data", y="y_data", hue="condition", legend=False, data=df)

# resize figure box to -> put the legend out of the figure
box = g.ax.get_position() # get position of figure
g.ax.set_position([box.x0, box.y0, box.width * 0.85, box.height]) # resize position

# Put a legend to the right side
g.ax.legend(loc='center right', bbox_to_anchor=(1.25, 0.5), ncol=1)

sns.plt.show(g)

也许您必须调整这些值以使其适合您的传奇。 如果您需要更多示例,This 的回答也会有所帮助。

【讨论】:

    【解决方案3】:

    我尝试将 T.W. 的答案应用于 seaborn lineplot,但没有成功。对他的答案进行一些修改就可以了……以防有人像我一样寻找线图版本!

    import seaborn as sns
    import pandas as pd
    
    # load data
    df = sns.load_dataset("gammas")
    
    # EDIT: I Needed to ad the fig
    fig, ax1 = plt.subplots(1,1)
    
    # EDIT: 
    # T.W.' answer said: "create with hue but without legend" <- # I needed to include it!
    # So, removed: legend=False
    g = sns.lineplot(x="timepoint", y="BOLD signal", hue="ROI", data=df, ax=ax1) 
    
    # EDIT: 
    # Removed 'ax' from T.W.'s answer here aswell:
    box = g.get_position()
    g.set_position([box.x0, box.y0, box.width * 0.85, box.height]) # resize position
    
    # Put a legend to the right side
    g.legend(loc='center right', bbox_to_anchor=(1.25, 0.5), ncol=1)
    
    plt.show()
    

    【讨论】:

    • 如果您在plt.show() 之前调用plt.tight_layout(),则无需移动绘图。此外,g.legend(loc='center left', bbox_to_anchor=(1.02, 0.5), ncol=1) 会将图例放在右侧,并锚定其左侧中心。
    【解决方案4】:

    seaborn解决方案:

    FacetGrid-based Seaborn plots 可以使用legend_out kwarg 自动执行此操作。使用relplot,通过facet_kws 字典将legend_out 传递给FacetGrid 构造函数:

    import seaborn as sns
    
    sns.set(style="darkgrid")
    
    gammas = sns.load_dataset("gammas")
    
    sns.relplot(
        data=gammas,
        x="timepoint",
        y="BOLD signal",
        hue="ROI",
        kind="line",
        facet_kws={"legend_out": True}
    )
    

    【讨论】:

    • 由于某种原因,facet_out=True 使用 seaborn 0.11.1 无效。
    • legend_out,不是 facet_out
    • 我的意思是legend_out。使用 seaborn 0.11.1 和 matplotlib 3.3.4。
    【解决方案5】:

    现有的解决方案似乎通过使用“错误”的位置参数使事情变得不必要地复杂;想想传说与锚的关系。例如,如果你想要一个图例在右边,那么锚点位置就是它的center left

    我们可以将 Sergey Antopolskiy 的回答简化为:

    import seaborn as sns
    
    # Load the long-form example gammas dataset
    g = sns.lineplot(data=gammas, x="timepoint", y="BOLD signal", hue="ROI")
    
    # Put the legend out of the figure
    g.legend(loc='center left', bbox_to_anchor=(1, 0.5))
    

    bbox_to_anchor 表示我们希望锚点位于右侧(即 x 轴上的 1)和垂直居中(y 轴上的 0.5)。 loc 说我们想要这个锚的左中角的图例。

    在 Seaborn 0.11.0 版中,这给了我类似的信息:

    【讨论】:

    • 这很有帮助。谢谢!
    • 这给了我一个'Legend' object is not callable 错误(seaborn 0.11.2)
    • @emilaz 认为您必须在做其他事情,它适用于 0.11.2
    • 是的,我这样做是为了一个 seaborn pairplot,这可能是原因:)
    猜你喜欢
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 2017-05-11
    相关资源
    最近更新 更多