matplotlib 如何为每个索引用百分比注解分组条形图

46scxncf  于 2023-05-07  发布在  其他
关注(0)|答案(1)|浏览(191)

我用下面的代码创建了一个条形图。我想为每个用户标记总计为~100%的百分比,就像我在下面的user 1和user 2的MSpaint中所做的那样:

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()

根据this thread的建议,我做了以下尝试:

尝试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()

尝试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()

尝试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()

shyt4zoc

shyt4zoc1#

绘制df,但创建一个百分比的 Dataframe ,它可以用作.bar_label的自定义labels

# 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()

注解分组水平条形图的代码kind='barh'完全相同。

# 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

相关问题