pandas 使用 DataFrame.plot 在堆积条形图中显示总计和百分比

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51495982/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 05:49:59  来源:igfitidea点击:

Display totals and percentage in stacked bar chart using DataFrame.plot

pythonpandasmatplotlib

提问by Hyman

My data frame looks like below:

我的数据框如下所示:

  Airport  ATA Cost  Destination Handling  Custom  Total Cost
0     PRG    599222                 11095   20174      630491
1     LXU    364715                 11598   11595      387908
2     AMS    401382                 23562   16680      441623
3     PRG    599222                 11095   20174      630491 

Using below codes it gives a stacked bar chart:

使用下面的代码,它给出了一个堆积条形图:

df = df.iloc[:, 0:4]    
df.plot(x='Airport', kind='barh', stacked=True, title='Breakdown of Costs', mark_right=True)    

enter image description here

在此处输入图片说明

How to add the totals (separated by thousands 1,000) over each stacked bar chart? How to add %for each segments in the stacked bar chart?

如何在每个堆积条形图上添加总数(以千 1,000 分隔)?如何为%堆积条形图中的每个段添加?

回答by SpghttCd

You can use plt.textto place the information at the positions according to your data.

您可以使用plt.text根据您的数据将信息放置在位置。

However, if you have very small bars, it might need some tweaking to look perfect.

但是,如果您的条形非常小,则可能需要进行一些调整才能看起来完美。

df_total = df['Total Cost']
df = df.iloc[:, 0:4]
df.plot(x = 'Airport', kind='barh',stacked = True, title = 'Breakdown of Costs', mark_right = True)

df_rel = df[df.columns[1:]].div(df_total, 0)*100

for n in df_rel:
    for i, (cs, ab, pc, tot) in enumerate(zip(df.iloc[:, 1:].cumsum(1)[n], df[n], df_rel[n], df_total)):
        plt.text(tot, i, str(tot), va='center')
        plt.text(cs - ab/2, i, str(np.round(pc, 1)) + '%', va='center', ha='center')

enter image description here

在此处输入图片说明

EDIT: Some arbitrary ideas for better readability:

编辑:一些随意的想法以获得更好的可读性:

shift the total values to the right, use 45° rotated text:

将总值向右移动,使用 45° 旋转文本:

    plt.text(tot+10000, i, str(tot), va='center')
    plt.text(cs - ab/2, i, str(np.round(pc, 1)) + '%', va='center', ha='center', rotation=45)

enter image description here

在此处输入图片说明

switch between top- and bottom-aligned text:

在上对齐和下对齐文本之间切换:

va = ['top', 'bottom']
va_idx = 0
for n in df_rel:
    va_idx = 1 - va_idx
    for i, (cs, ab, pc, tot) in enumerate(zip(df.iloc[:, 1:].cumsum(1)[n], df[n], df_rel[n], df_total)):
        plt.text(tot+10000, i, str(tot), va='center')
        plt.text(cs - ab/2, i, str(np.round(pc, 1)) + '%', va=va[va_idx], ha='center')

enter image description here

在此处输入图片说明

label only bars with 10% or more:

仅标记 10% 或更多的条形:

if pc >= 10:
    plt.text(cs - ab/2, i, str(np.round(pc, 1)) + '%', va='center', ha='center')

enter image description here

在此处输入图片说明

...or still print them, but vertical:

...或仍然打印它们,但垂直:

if pc >= 10:
    plt.text(cs - ab/2, i, str(np.round(pc, 1)) + '%', va='center', ha='center')
else:
    plt.text(cs - ab/2, i, str(np.round(pc, 1)) + '%', va='center', ha='center', rotation=90)

enter image description here

在此处输入图片说明