【问题标题】:Disable hue nesting in Seaborn在 Seaborn 中禁用色调嵌套
【发布时间】:2020-06-10 09:31:02
【问题描述】:

使用 Seaborn 绘制条形图并使用 hue 参数根据其列值对条形进行着色时,具有相同列值的条将嵌套或聚合,并且仅显示单个条。下图说明了这个问题。 1 号患者有两个样本 sample_type1,值分别为 10 和 20。这两个值已嵌套,两个值都表示为单个条形(作为两者的平均值)。 我想避免这种嵌套,而是在下图中有类似的东西。 这有可能实现吗? MVE 下面。谢谢!

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.DataFrame({
    "patient_number": [1, 1, 1, 2, 2, 2],
    "sample_type": [1, 1, 2, 1, 2, 3],
    "value": [10, 20, 15, 10, 11, 12]
})

sns.barplot(x="patient_number", y="value", hue="sample_type", data=df)
plt.show()

【问题讨论】:

  • 您的问题无法给出一般答案。只有当每个患者都有大约相同数量的样本时,它才会起作用。例如,如果患者 3 有 10 个类型 3 的样本会发生什么?
  • 那么我想要 x=3 的 10 个绿色条。不过,在这个数据集中,患者都有 3-4 个样本。

标签: python pandas seaborn


【解决方案1】:

以下方法获得所需的情节:

  • Seaborn 的 hue= 参数都定义了条形的颜色和位置。
  • 对于每位患者,额外字段 ('idx') 包含每个所需条形的唯一编号。对于下一位患者,该字段“idx”从 0 重新开始,并添加到数据框中。
  • 'idx' 然后可以用作hue='idx' 以获取所需的列,尽管它们将按顺序着色。
  • 为了获得每种样本类型的一种颜色,一个额外的列现在包含样本类型的分解版本(因此,第一种类型为 0,下一种类型为 1,等等)
  • Seaborn 会根据色调生成条形图,每个患者一个。这些条可以通过ax.patches 以列表的形式访问
  • 通过遍历患者,然后遍历“idx”,可以通过“sample_type”访问所有条形并为其着色。由于条形的排序有点棘手,因此需要进行适当的重新编号。
  • 需要更改图例以反映样本类型。

对给定的数据进行了一些扩展,以便能够测试每位患者不同数量的样本,以及不是简单后续数字的样本类型。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.DataFrame({
    'patient_number': [1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3],
    'sample_type': ['st1', 'st1', 'st2', 'st1', 'st2', 'st3', 'st4', 'st4', 'st4', 'st4', 'st4'],
    'value': [10, 20, 15, 10, 11, 12, 1, 2, 3, 4, 5]
})
df['idx'] = df.groupby('patient_number').cumcount()
df['sample_factors'], sample_labels = pd.factorize(df['sample_type'])

ax = sns.barplot(x='patient_number', y='value', hue='idx', data=df)

colors = plt.cm.get_cmap('Set2').colors  # https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html
handles = [None for _ in sample_labels]
num_patients = len(ax.patches) // (df['idx'].max() + 1)
for i, (patient_id, group) in enumerate(df.groupby('patient_number')):
    for j, factor in enumerate(group['sample_factors']):
        patch = ax.patches[i + j * num_patients]
        patch.set_color(colors[factor])
        handles[factor] = patch

ax.legend(handles=handles, labels=list(sample_labels), title='Sample type')

plt.show()

【讨论】:

  • 多么出色的答案,这完美无瑕。我需要花几分钟的时间来了解这里发生的一切。谢谢!
猜你喜欢
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多