1 回答

TA贡献1820条经验 获得超3个赞
可以通过从 中提取条形位置来注释条形图
ax.patches
。补丁数据不包含与数据帧相对应的标签,因此关联不同的数据值集成为一个定制过程。
为了用
Value
代替进行注释Price
,需要有一种方法来关联相应的值。字典不起作用,因为有重复值
为 制作一个旋转数据框
Value
和 的相应数据框Price
。这将确保相应的数据位于同一位置。
col_idx
和row_idx
将与 一起使用.iloc
来查找 中的正确值df_value
,并用它来注释绘图。col_idx
和row_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
添加回答
举报