如何修改 seaborn 图以获取每类的百分比信息?

Posted

技术标签:

【中文标题】如何修改 seaborn 图以获取每类的百分比信息?【英文标题】:How to modify seaborn graph to have percentage information per class? 【发布时间】:2022-01-12 01:24:44 【问题描述】:

我正在使用以下代码来绘制退货/未退货产品百分比(y 轴)相对于这些产品的折扣百分比(x 轴)。如果您看到,所有条形图都将增加到 100%。

sns.histplot(data=df_c, x='percent_discount_100', hue='returned',binwidth=10, stat='percent', ax=ax)
#ax.set_xlim(1,31)
#ax.set_xticks(range(0,100,10))
plt.show()

我想要更改每个条的百分比信息,我的意思是,对于每个条,我想添加退回和未退回的产品百分比(对于每个条,显然百分比将增加到 100%) .您能告诉我如何解决这个问题吗?

也可以添加使用其他库的解决方案,例如 plotly 和 matplotlib。

【问题讨论】:

这能回答你的问题吗? How to annotate barplot with percent by hue/legend group 和How to add percentages on top of bars in seaborn 和How to plot percentage with seaborn distplot / histplot / displot @TrentonMcKinney 不是真的,我希望每个条添加到 100%,返回和未返回描述它们的百分比(例如,第一个条可能有 10% 的返回和 90% 的未返回) ,所以在某种程度上,我认为所有条形都可以具有相同的高度,只是返回和未返回的比例不同。 这个问题需要SSCCE。请参阅How to ask a good question。始终提供完整的minimal reproducible example,其中包含代码、数据、错误、当前输出和预期输出,如formatted text。如果相关,只有绘图图像是可以的。如果您不包含 mre,则该问题可能会被否决、关闭和删除。 我的 x 轴也没有分类变量:没关系。 .bar_label 可以正常工作,因为这些是标签,而不是条形的实际位置,如 如何使用 seaborn distplot / histplot / displot 绘制百分比中所示 【参考方案1】:

Seaborn 只是一种轻松探索数据的工具,并不完美。如果您想让图形可发布,请使用任何必要的工具。在您的情况下,pandas + matplotlib 是更好的选择。

如果没有给出数据,我假设你的数据是这样的(如果没有,就这样吧):

In [33]: df2 = pd.DataFrame(np.random.rand(10, 4), columns=["a", "b", "c", "d"])
In [34]: df2
Out[34]: 
          a         b         c         d
0  0.440042  0.509648  0.863190  0.532108
1  0.087648  0.695300  0.830660  0.468570
2  0.807494  0.195466  0.911627  0.278780
3  0.870929  0.971947  0.997894  0.780992
4  0.205380  0.097973  0.803379  0.100402
5  0.958186  0.362425  0.915435  0.585129
6  0.961905  0.196360  0.080999  0.933527
7  0.785202  0.497949  0.992512  0.518781
8  0.874882  0.610012  0.348986  0.996064
9  0.424615  0.135498  0.931710  0.619083

然后,将其转换为百分比,在df3 中,每行总和为1.0:

In [46]: df3 = df2.apply(lambda x: x / sum(x) * 100, axis=1)

In [47]: df3
Out[47]: 
           a          b          c          d
0  18.765234  21.733508  36.809987  22.691272
1   4.209449  33.392931  39.893775  22.503845
2  36.815260   8.911695  41.562896  12.710148
3  24.047114  26.836290  27.552722  21.563874
4  17.013872   8.116157  66.552564   8.317407
5  33.964091  12.846603  32.448702  20.740605
6  44.270478   9.037220   3.727897  42.964405
7  28.098676  17.819245  35.517338  18.564740
8  30.915164  21.555626  12.331912  35.197297
9  20.115278   6.418958  44.137918  29.327846

如果你只是想看看相对差异,

df3.plot.bar(stacked=True)

如果您想在条形上方添加百分比,请参阅How to display the value of the bar on each bar with pyplot.barh()

【讨论】:

【参考方案2】:

使用multiple='fill',条形将被拉伸以填充 100%。

这是一个使用 Titanic 数据集的示例:

from matplotlib import pyplot as plt
from matplotlib.ticker import PercentFormatter
import seaborn as sns

titanic = sns.load_dataset('titanic')
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12, 4))
for ax, multiple in zip((ax1, ax2), ['layer', 'fill']):
    sns.histplot(data=titanic, x='age', hue='sex', binwidth=10, stat='percent', multiple=multiple, ax=ax)
    ax.set_title(f"multiple='multiple'")
# ax.bar_label(ax.containers[0], fmt='%.2f',label_type='center', color='black')
# ax.bar_label(ax.containers[1], fmt='%.2f', label_type='center', color='white')
for bar_group, color in zip(ax.containers, ['black', 'white']):
    ax.bar_label(bar_group, label_type='center', color=color,
                 labels=[f'bar.get_height() * 100:.1f %' if bar.get_height() > 0 else '' for bar in bar_group])
ax.yaxis.set_major_formatter(PercentFormatter(1))
plt.tight_layout()
plt.show()

【讨论】:

谢谢,这就是我要找的答案。 如果这回答了您的问题,您可以考虑将答案标记为已接受

以上是关于如何修改 seaborn 图以获取每类的百分比信息?的主要内容,如果未能解决你的问题,请参考以下文章

如何在seaborn的条形顶部添加百分比

如何在seaborn的条形顶部添加百分比

Seaborn:如何在绘图的 X 轴上的每个值之后添加一个“%”符号,而不是将值转换为百分比? [复制]

Seaborn:如何将每个分类值的 Y 轴缩放到 100%

如何更改 seaborn countplot 中图例的位置?

如何将 y 轴转换为 Seaborn 图中的 % 值? [复制]