使用 seaborn 绘图时,如何为色调参数指定多个变量?

Posted

技术标签:

【中文标题】使用 seaborn 绘图时,如何为色调参数指定多个变量?【英文标题】:How can I specify multiple variables for the hue parameters when plotting with seaborn? 【发布时间】:2020-06-07 12:29:01 【问题描述】:

当使用 seaborn 时,有没有办法可以为 hue 参数包含多个变量(列)?问这个问题的另一种方法是如何在将数据绘制在单个 x,y 轴图上之前按多个变量对数据进行分组?

我想做类似下面的事情。但是目前我无法为 hue 参数指定两个变量。:

sns.relplot(x='#', y='Attack', hue=['Legendary', 'Stage'], data=df)

例如,假设我有一个如下所示的 pandas DataFrame,其中包含通过 this 教程获得的 Pokemon database。

我想在 x 轴上绘制 pokedex #,在 y 轴上绘制 Attack。但是,我希望数据按 StageLegendary 进行分组。使用 matplotlib,我编写了一个自定义函数,将数据框按 ['Legendary','Stage'] 分组,然后遍历每个组以进行绘图(请参见下面的结果)。尽管我的自定义功能按预期工作,但我希望这可以通过 seaborn 简单地实现。我猜肯定有其他人试图使用 seaborn 在单个图中可视化超过 3 个变量?

fig, ax = plt.subplots()
grouping_variables = ['Stage','Legendary']
group_1 = df.groupby(grouping_variables)
for group_1_label, group_1_df in group_1:
    ax.scatter(group_1_df['#'], group_1_df['Attack'], label=group_1_label)
ax_legend = ax.legend(title=grouping_variables)    

编辑1:

注意:在我提供的示例中,我仅按两个变量(例如:传奇和舞台)对数据进行了分组。但是,其他情况可能需要任意数量的变量(例如:5 个变量)。

【问题讨论】:

【参考方案1】:

您可以利用 hue 接受列名或与您的数据长度相同的序列这一事实,列出要分配每个数据点的颜色类别。所以……

sns.relplot(x='#', y='Attack', hue='Stage', data=df)

... 与:

基本相同
sns.relplot(x='#', y='Attack', hue=df['Stage'], data=df)

你通常不会使用后者,它只是为了达到同样的目的而需要更多的输入——除非你想动态地构建一个自定义序列:

sns.relplot(x='#', y='Attack', data=df,
            hue=df[['Legendary', 'Stage']].apply(tuple, axis=1))

您构建通过hue 传递的序列的方式完全取决于您,唯一的要求是它必须与您的数据具有相同的长度,如果是类似数组,它必须是一维的,所以你不能只传递hue=df[['Legendary', 'Stage']],你必须以某种方式将这些列连接成一个。我选择tuple 作为最简单、最通用的方式,但如果你想对格式有更多的控制,请构建一个Series 的字符串。为了更好的可读性,我将它保存到一个单独的变量中,这样我就可以为它指定一个名称(将用作图例标题),但您不必:

hue = df[['Legendary', 'Stage']].apply(
    lambda row: f"row.Legendary, row.Stage", axis=1)
hue.name = 'Legendary, Stage'
sns.relplot(x='#', y='Attack', hue=hue, data=df)

【讨论】:

【参考方案2】:

要使用seaborn.relplothue,请考虑将所需的组连接到单个列中,然后在新变量上运行绘图:

def run_plot(df, flds):
   # CREATE NEW COLUMN OF CONCATENATED VALUES
   df['_'.join(flds)] =  pd.Series(df.reindex(flds, axis='columns')
                                     .astype('str')
                                     .values.tolist()
                                  ).str.join('_')

   # PLOT WITH hue
   sns.relplot(x='#', y='Attack', hue='_'.join(flds), data=random_df, aspect=1.5)
   plt.show()

   plt.clf()
   plt.close()

用随机数据演示

数据

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns

### DATA
np.random.seed(22320)
random_df = pd.DataFrame('#': np.arange(1,501),
                          'Name': np.random.choice(['Bulbasaur', 'Ivysaur', 'Venusaur', 
                                                    'Charmander', 'Charmeleon'], 500),
                          'HP': np.random.randint(1, 100, 500),
                          'Attack': np.random.randint(1, 100, 500),
                          'Defense': np.random.randint(1, 100, 500),
                          'Sp. Atk': np.random.randint(1, 100, 500),
                          'Sp. Def': np.random.randint(1, 100, 500),
                          'Speed': np.random.randint(1, 100, 500),
                          'Stage': np.random.randint(1, 3, 500),
                          'Legend': np.random.choice([True, False], 500)
                          )

run_plot(random_df, ['Legend', 'Stage'])

run_plot(random_df, ['Legend', 'Stage', 'Name'])

【讨论】:

【参考方案3】:

在 seaborn 的 scatterplot() 中,您可以结合 hue=style= 参数来为每种组合生成不同的标记和不同的颜色

示例(逐字取自the documentation):

tips = sns.load_dataset("tips")
ax = sns.scatterplot(x="total_bill", y="tip", data=tips)
ax = sns.scatterplot(x="total_bill", y="tip",
                     hue="day", style="time", data=tips)

【讨论】:

很好,但不是问题的主题。

以上是关于使用 seaborn 绘图时,如何为色调参数指定多个变量?的主要内容,如果未能解决你的问题,请参考以下文章

使用 seaborn 绘图时如何处理缺失值?

使用色调参数在seaborn中分割小提琴图

如何为绘图甘特图中的元素指定颜色?

Seaborn - 添加色调时时间序列换行

机器学习——可视化绘图matplotlib和seaborn

分类属性绘图(seaborn的catplot函数)