【问题标题】:Stacked clustered percentage bar with labels带标签的堆叠聚集百分比条
【发布时间】:2020-09-20 00:04:42
【问题描述】:

我有以下多索引数据框

data_json="""{"Group":{"0":"G1","1":"G1","2":"G2","3":"G2","4":"G3","5":"G3"},
            "Letter":{"0":"A","1":"B","2":"A","3":"B","4":"A","5":"B"},
            "Percentage":{"0":0.5,"1":0.2,"2":0.3,"3":0.5,"4":0.7,"5":0.7},
            "1-Percentage":{"0":0.5,"1":0.8,"2":0.7,"3":0.5,"4":0.3,"5":0.3}}"""

df=pd.read_json(data_json).set_index(['Group','Letter'])
df
Out[152]: 
              Percentage  1-Percentage
Group Letter                          
G1    A              0.5           0.5
      B              0.2           0.8
G2    A              0.3           0.7
      B              0.5           0.5
G3    A              0.7           0.3
      B              0.7           0.3

json 输出:

有没有办法重现下图?

到目前为止,我只设法获得了堆叠图,但现在仍然不知道如何在 x 轴上显示多级,也不能将标签添加到条形图上,这是迄今为止的代码和结果:


plotdata=plotdata*100

plotdata.plot(kind='bar',stacked=True)
plt.show()

【问题讨论】:

    标签: pandas matplotlib plot


    【解决方案1】:

    试试这段代码:

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from itertools import groupby
    
    d = {'Percentage': {('G1', 'A'): 50.0,
      ('G1', 'B'): 20.0,
      ('G2', 'A'): 30.0,
      ('G2', 'B'): 50.0,
      ('G3', 'A'): 70.0,
      ('G3', 'B'): 70.0},
     '1-Percentage': {('G1', 'A'): 50.0,
      ('G1', 'B'): 80.0,
      ('G2', 'A'): 70.0,
      ('G2', 'B'): 50.0,
      ('G3', 'A'): 30.0,
      ('G3', 'B'): 30.0}}
    
    plotdata = pd.DataFrame(d)
    
    def add_line(ax, xpos, ypos):
        line = plt.Line2D([xpos, xpos], [ypos + .1, ypos],
                          transform=ax.transAxes, color='gray')
        line.set_clip_on(False)
        ax.add_line(line)
    
    def label_len(my_index,level):
        labels = my_index.get_level_values(level)
        return [(k, sum(1 for i in g)) for k,g in groupby(labels)]
    
    def label_group_bar_table(ax, df):
        ypos = -.1
        scale = 1./df.index.size
        for level in range(df.index.nlevels)[::-1]:
            pos = 0
            for label, rpos in label_len(df.index,level):
                lxpos = (pos + .5 * rpos)*scale
                ax.text(lxpos, ypos, label, ha='center', transform=ax.transAxes)
                add_line(ax, pos*scale, ypos)
                pos += rpos
            add_line(ax, pos*scale , ypos)
            ypos -= .1
    
    ax = plotdata.plot(kind='bar',stacked=True)
    ax.set_xticklabels('')
    ax.set_xlabel('')
    label_group_bar_table(ax, plotdata)
    

    用于记录,zip 中的标签(ax.patches,plotdata['Percentage'].round(0).astype(int).astype(str)+'%'):
    高度 = rec.get_height()
    ax.text(rec.get_x() + rec.get_width() / 2, 高度 / 2, 标签,
    ha = 'center', va='bottom', color='w')

    #Update using matplotlib 3.4.2
    
    for c in ax.containers[::2]:
        ax.bar_label(c, label_type='center', fmt='%0.0f%%', padding=10, color='w')
    

    输出图表:

    【讨论】:

    • @AndrésBraga 这个解决方案对您有帮助吗?
    猜你喜欢
    • 1970-01-01
    • 2021-07-01
    • 2012-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-18
    相关资源
    最近更新 更多