【问题标题】:How to add annotations to Stack Percentage Barplot in Matplotlib如何在 Matplotlib 中向 Stack Percentage Barplot 添加注释
【发布时间】:2021-05-10 23:53:18
【问题描述】:

我想使用 matplotlib 向堆积条形图添加值。到目前为止,我已经能够创建堆叠条形图,但我对如何添加注释感到困惑。

here 已经回答了一个类似的问题,但针对的是 ggplot。

我想要的输出类似于不是整个图表,而只是中间的注释。

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


data = {'Range':['<10','>10', '>= 20', '<10','>10', '>= 20', '<10','>10', '>= 20'],
    'Price':[50,25,25,70,20,10,80,10,10]
    'Value':[100,50,50,140,40,20,160,20,20]}    

df1 = pd.DataFrame(data)

b1 = df1[(df1['Range'] == '<10']['Price']
b2 = df1[df1['Range'] == '>10']['Price']
b3 = df1[df1['Range'] == '>= 20']['Price']

totals = [i+j+k for i,j,k in zip(b1,b2,b3)]
greenBars = [i / j * 100 for i,j in zip(b1, totals)]
orangeBars = [i / j * 100 for i,j in zip(b2, totals)]
blueBars = [i / j * 100 for i,j in zip(b3, totals)]


barWidth = 0.5

names = ('low', 'medium', 'high')
r = [0,1,2]
plt.bar(r, greenBars, color='#b5ffb9', edgecolor='white', width=barWidth, label = '$<10')
plt.bar(r, orangeBars, bottom=greenBars, color='#f9bc86', edgecolor='white', width=barWidth, label = '$>10')
plt.bar(r, blueBars, bottom=[i+j for i,j in zip(greenBars, orangeBars)], color='#a3acff', edgecolor='white', width=barWidth, label = '$>=20')


plt.xticks(r, names)
plt.xlabel("group")

plt.legend(loc='upper left', bbox_to_anchor=(1,1), ncol=1)

plt.show()

在上面添加了代码以创建堆叠图。 期望的输出:

对于 Low 类别,通过从列 Value 中提取 100、50 和 50 的值,在堆栈上添加注释

对于中值,值为 140、40 和 20。

对于高值将是 160、20 和 20。

【问题讨论】:

    标签: python pandas matplotlib seaborn stacked-chart


    【解决方案1】:
    • 此答案将根据Quang Hoang 中的代码简化绘图
    • 可以通过从ax.patches 中提取条形位置来注释条形图。
      • 补丁数据不包含对应于数据框的标签,因此关联不同的数据值集成为一个定制过程。
    • 为了使用Value 而不是Price 进行注释,需要有一种方法来关联相应的值。
      • 字典不起作用,因为存在重复值
      • Value 制作一个旋转数据框,为Price 制作一个相应的数据框。这将确保相应的数据位于同一位置。
    • col_idxrow_idx 将与 .iloc 一起使用,以在 df_value 中找到正确的值,用于注释绘图。
      • col_idxrow_idx 都可以在if i%3 == 0 中重置或更新,因为有 3 条和 3 段,但是如果有不同的条和段数,则需要不同的重置条件。李>
    import pandas as pd
    import matplotlib.pyplot as plt
    
    # create the dataframe
    data = {'Range':['<10','>10', '>= 20', '<10','>10', '>= 20', '<10','>10', '>= 20'],
            'Price':[50,25,25,70,20,10,80,10,10],
            'Value':[100,50,50,140,40,20,160,20,20]}    
    
    df1 = pd.DataFrame(data)
    
    # pivot the price data
    df_price = df1.assign(idx=df1.groupby('Range').cumcount()).pivot(index='idx', columns='Range', values='Price')
    
    Range  <10  >10  >= 20
    idx                   
    0       50   25     25
    1       70   20     10
    2       80   10     10
    
    # pivot the value data
    df_value = df1.assign(idx=df1.groupby('Range').cumcount()).pivot(index='idx', columns='Range', values='Value')
    
    Range  <10  >10  >= 20
    idx                   
    0      100   50     50
    1      140   40     20
    2      160   20     20
    
    # set colors
    colors = ['#b5ffb9', '#f9bc86', '#a3acff']
    
    # plot the price
    ax = df_price.plot.bar(stacked=True, figsize=(8, 6), color=colors, ec='w')
    
    # label the x-axis
    plt.xticks(ticks=range(3), labels=['low', 'med', 'high'], rotation=0)
    
    # x-axis title
    plt.xlabel('group')
    
    # position the legend
    plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
    
    # annotate the bar segments
    # col and row iloc indices for df_value
    col_idx = 0
    row_idx = 0
    
    # iterate through each bar patch from ax
    for i, p in enumerate(ax.patches, 1):
    
        left, bottom, width, height = p.get_bbox().bounds
        v = df_value.iloc[row_idx, col_idx]
        if width > 0:
            ax.annotate(f'{v:0.0f}', xy=(left+width/2, bottom+height/2), ha='center', va='center')
    
            # use this line to add commas for thousands
    #        ax.annotate(f'{v:,}', xy=(left+width/2, bottom+height/2), ha='center', va='center')
        
        row_idx += 1
        if i%3 == 0:  # there are three bars, so update the indices 
            col_idx += 1
            row_idx = 0
    

    【讨论】:

      猜你喜欢
      • 2021-08-01
      • 2020-04-26
      • 2011-12-16
      相关资源
      最近更新 更多