基于两列的 seaborn 范围背景

Posted

技术标签:

【中文标题】基于两列的 seaborn 范围背景【英文标题】:Background with range on seaborn based on two columns 【发布时间】:2021-05-15 14:07:55 【问题描述】:

我正在尝试在我的几个线图中添加一个背景,该背景显示每年从值 x(列“Min”)到值 y(列“Max”)的范围。我的数据集如下所示:

        Country Model   Year    Costs   Min Max
    494 FR  1   1990    300     250     350
    495 FR  1   1995    250     300     400
    496 FR  1   2000    220     330     640
    497 FR  1   2005    210     289     570
    498 FR  2   1990    400     250     350
    555 JPN 8   1990    280     250     350
    556 JPN 8   1995    240     300     400
    557 JPN 8   2000    200     330     640
    558 JPN 8   2005    200     289     570

我使用了以下代码:

example_1 = sns.relplot(data=example, x = "Year", y = "Costs", hue = "Model", style = "Model", col = "Country", kind="line", col_wrap=4,height = 4, dashes = True, markers = True, palette = palette, style_order = style_order)

我想要这样的东西,范围是我每年的“最小”和“最大”。

有可能吗? 非常感谢!

【问题讨论】:

我的回答是否提供了您正在寻找的解决方案? 你好帕特里克!您的回答正是我正在寻找的解决方案!非常感谢您的详细解释! 【参考方案1】:

通常,grid.map 是执行此操作的工具,如mutli-plot grids tutorial 中的许多示例所示。但是您正在使用 relplotlineplotFacetGrid 组合在一起,因为建议使用 in the docs(最后一个示例),这可以让您使用一些额外的样式参数。

因为relplot 处理数据的方式与您首先启动FacetGrid 然后映射lineplot(您可以使用grid.data 进行检查)略有不同,因此使用grid.map(plt.bar, ...) 绘制范围是相当麻烦,因为它需要编辑 grid.data 数据框以及 x 轴和 y 轴标签。

绘制范围最简单的方法是循环遍历grid.axes。这可以通过grid.axes_dict.items() 来完成,它提供了列名称(即国家/地区),您可以使用这些名称为条形选择适当的数据(如果范围不同,则很有用,与本示例相反)。

默认图形图例不包含完整的图例,包括范围的键,但第一个 ax 对象会显示一个而不是以下示例中的默认图例。请注意,我已经编辑了您共享的数据,以便最小/最大范围更有意义:

import io
import pandas as pd              # v 1.1.3
import matplotlib.pyplot as plt  # v 3.3.2
import seaborn as sns            # v 0.11.0

data ='''
 Country Model   Year    Costs   Min Max
    494 FR  1   1990    300     250     350
    495 FR  1   1995    250     200     300
    496 FR  1   2000    220     150     240
    497 FR  1   2005    210     189     270
    555 JPN 8   1990    280     250     350
    556 JPN 8   1995    240     200     300
    557 JPN 8   2000    200     150     240
    558 JPN 8   2005    200     189     270
'''
df = pd.read_csv(io.StringIO(data), delim_whitespace=True)

# Create seaborn FacetGrid with line plots
grid = sns.relplot(data=df, x='Year', y='Costs', hue='Model', style='Model',height=3.9,
                   col='Country', kind='line', markers=True, palette='tab10')

# Loop through axes of the FacetGrid to plot bars for ranges and edit x ticks
for country, ax in grid.axes_dict.items():
    df_country = df[df['Country'] == country]
    cost_range = df_country['Max']-df_country['Min']
    ax.bar(x=df_country['Year'], height=cost_range, bottom=df_country['Min'], 
           color='black', alpha=0.1, label='Min/max\nrange')
    ax.set_xticks(df_country['Year'])

# Remove default seaborn figure legend and show instead full legend stored in first ax
grid._legend.remove()
grid.axes.flat[0].legend(bbox_to_anchor=(2.1, 0.5), loc='center left',
                         frameon=False, title=grid.legend.get_title().get_text());

【讨论】:

以上是关于基于两列的 seaborn 范围背景的主要内容,如果未能解决你的问题,请参考以下文章

使用 seaborn 绘图时转换 pandas 列中的数据类型

基于 DataFrame 列名的颜色 seaborn 箱线图

text 熊猫两列数据帧到10x10 seaborn热图

如何在不命名 DataFrame 列的情况下使用 Seaborn.lmplot 函数?

是否可以使用 seaborn 绘制超过 6 列的线图?

使用seaborn在python中绘制3列的热图