英文:
How to annotate grouped bars with percent for each index
问题
ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',
xlabel='Username', title='Discord Sentiment Analysis',
color=['coral', 'khaki', 'skyblue'])
for p in ax.patches:
width = p.get_width()
height = p.get_height()
x, y = p.get_xy()
ax.annotate(f'{height:.0%}', (x + width/2, y + height*1.02), ha='center')
plt.tight_layout()
plt.show()
英文:
I have created a bar plot with the following code. I would like to label the percentages adding up to ~100% for each user, as I've done in MSpaint for user1 and user2 below:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
users = ['user1', 'user2', 'user3', 'user4', 'user5', 'user6', 'user7',\
'user8', 'user9', 'user10', 'user11', 'user12']
NEG = [433, 1469, 1348, 2311, 522, 924, 54, 720, 317, 135, 388, 9]
NEU = [2529, 4599, 4617, 4297, 1782, 2742, 61, 2640, 1031, 404, 1723, 76]
POS = [611, 1149, 1262, 1378, 411, 382, 29, 513, 421, 101, 584, 49]
data = {'Negative': NEG, 'Neutral': NEU, 'Positive': POS}
df = pd.DataFrame(data, index=users)
ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\
xlabel='Username', title='Discord Sentiment Analysis',\
color=['coral', 'khaki', 'skyblue'])
plt.tight_layout()
plt.show()
Following the advice from this thread, I've made the following attempts:
Attempt 1
ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\
xlabel='Username', title='Discord Sentiment Analysis',\
color=['coral', 'khaki', 'skyblue'])
for p in ax.containers:
ax.bar_label(p, fmt='%.1f%%', label_type='edge')`
plt.tight_layout()
plt.show()
Attempt 2
ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\
xlabel='Username', title='Discord Sentiment Analysis',\
color=['coral', 'khaki', 'skyblue'])
for p in ax.patches:
width = p.get_width()
height = p.get_height()
x, y = p.get_xy()
ax.annotate(f'{height:.0%}', (x + width/2, y + height*1.02), ha='center')
plt.tight_layout()
plt.show()
Attempt 3
ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\
xlabel='Username', title='Discord Sentiment Analysis',\
color=['coral', 'khaki', 'skyblue'])
for p in ax.containers:
ax.bar_label(p, fmt='%.1f%%', label_type='edge')
plt.tight_layout()
plt.show()
答案1
得分: 4
- 创建一个百分比的数据框,可用作
.bar_label
的自定义标签。 - 详细说明以及
.bar_label
的其他示例,请参阅如何在条形图上添加值标签。
# 创建百分比数据框
percent = df.div(df.sum(axis=1), axis=0).mul(100).round(1)
# 绘图
ax = df.plot(kind='bar', ylabel='消息数\n(<= 128字符)',
xlabel='用户名', title='Discord情感分析',
color=['coral', 'khaki', 'skyblue'], width=0.9, figsize=(10, 8))
# 添加注释
for p in ax.containers:
# 获取当前图例标签,即列名
label = p.get_label()
# 使用列名从百分比中访问正确的标签
labels = percent[label].astype(str).add('%')
# 添加条形标签
ax.bar_label(p, labels=labels, label_type='edge', rotation=90, fontsize=10, padding=3)
# 增加数字与图表边缘之间的间距
ax.margins(y=0.1)
plt.tight_layout()
plt.show()
用于注释分组水平条形图kind='barh'
的代码完全相同。
# 创建百分比数据框
percent = df.div(df.sum(axis=1), axis=0).mul(100).round(1)
# 绘图
ax = df.plot(kind='barh', ylabel='消息数\n(<= 128字符)',
xlabel='用户名', title='Discord情感分析',
color=['coral', 'khaki', 'skyblue'], width=0.9, figsize=(10, 8))
# 添加注释
for p in ax.containers:
label = p.get_label()
labels = percent[label].astype(str).add('%')
ax.bar_label(p, labels=labels, label_type='edge', rotation=0, fontsize=10, padding=3)
# 增加数字与图表边缘之间的间距
ax.margins(x=0.1)
plt.tight_layout()
plt.show()
df
负面情感 中性情感 正面情感
user1 433 2529 611
user2 1469 4599 1149
user3 1348 4617 1262
user4 2311 4297 1378
user5 522 1782 411
user6 924 2742 382
user7 54 61 29
user8 720 2640 513
user9 317 1031 421
user10 135 404 101
user11 388 1723 584
user12 9 76 49
percent
负面情感 中性情感 正面情感
user1 12.1 70.8 17.1
user2 20.4 63.7 15.9
user3 18.7 63.9 17.5
user4 28.9 53.8 17.3
user5 19.2 65.6 15.1
user6 22.8 67.7 9.4
user7 37.5 42.4 20.1
user8 18.6 68.2 13.2
user9 17.9 58.3 23.8
user10 21.1 63.1 15.8
user11 14.4 63.9 21.7
user12 6.7 56.7 36.6
英文:
- Plot
df
, but create a dataframe of the percents, which can be used as customlabels
for.bar_label
. - See How to add value labels on a bar chart for a thorough explanation, and additional examples, of
.bar_label
.
# create a dataframe of percents
percent = df.div(df.sum(axis=1), axis=0).mul(100).round(1)
# plot
ax = df.plot(kind='bar', ylabel='Number of Messages\nw/ <= 128 Characters',\
xlabel='Username', title='Discord Sentiment Analysis',\
color=['coral', 'khaki', 'skyblue'], width=0.9, figsize=(10, 8))
# add annotations
for p in ax.containers:
# get the current legend label, which is the column name
label = p.get_label()
# use the column name to access the correct labels from percent
labels = percent[label].astype(str).add('%')
# add the bar labels
ax.bar_label(p, labels=labels, label_type='edge', rotation=90, fontsize=10, padding=3)
# pad the spacing between the number and the edge of the figure
ax.margins(y=0.1)
plt.tight_layout()
plt.show()
The code for annotating a grouped horizontal bar chart, kind='barh'
, is exactly the same.
# create a dataframe of percents
percent = df.div(df.sum(axis=1), axis=0).mul(100).round(1)
# plot
ax = df.plot(kind='barh', ylabel='Number of Messages\nw/ <= 128 Characters',\
xlabel='Username', title='Discord Sentiment Analysis',\
color=['coral', 'khaki', 'skyblue'], width=0.9, figsize=(10, 8))
# add annotations
for p in ax.containers:
label = p.get_label()
labels = percent[label].astype(str).add('%')
ax.bar_label(p, labels=labels, label_type='edge', rotation=0, fontsize=10, padding=3)
# pad the spacing between the number and the edge of the figure
ax.margins(x=0.1)
plt.tight_layout()
plt.show()
df
Negative Neutral Positive
user1 433 2529 611
user2 1469 4599 1149
user3 1348 4617 1262
user4 2311 4297 1378
user5 522 1782 411
user6 924 2742 382
user7 54 61 29
user8 720 2640 513
user9 317 1031 421
user10 135 404 101
user11 388 1723 584
user12 9 76 49
percent
Negative Neutral Positive
user1 12.1 70.8 17.1
user2 20.4 63.7 15.9
user3 18.7 63.9 17.5
user4 28.9 53.8 17.3
user5 19.2 65.6 15.1
user6 22.8 67.7 9.4
user7 37.5 42.4 20.1
user8 18.6 68.2 13.2
user9 17.9 58.3 23.8
user10 21.1 63.1 15.8
user11 14.4 63.9 21.7
user12 6.7 56.7 36.6
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论