python - 如何仅注释堆叠条形图的一个类别
问题描述
我有一个数据框示例,如下所示。
data = {'Date':['2021-07-18','2021-07-19','2021-07-20','2021-07-21','2021-07-22','2021-07-23'],
'Invalid':["NaN", 1, 1, "NaN", "NaN", "NaN"],
'Negative':[23, 24, 17, 24, 20, 23],
'Positive':["NaN", 1, 1, 1, "NaN", 1]}
df_sample = pd.DataFrame(data)
df_sample
下面给出了显示堆叠条形图的代码以及由它生成的图形。
temp = Graph1_df.set_index(['Dates', 'Results']).sort_index(0).unstack()
temp.columns = temp.columns.get_level_values(1)
f, ax = plt.subplots(figsize=(20, 5))
temp.plot.bar(ax=ax, stacked=True, width = 0.3, color=['blue','green','red'])
ax.title.set_text('Total Test Count vs Dates')
plt.show()
使用上面的代码或任何新方法,我只想在图表上显示“正”的值。注意:数据框片段中的第三列是“正”列。
任何帮助是极大的赞赏。谢谢。
解决方案
pandas.DataFrame.plot
用with绘图kind='bar'
- 用于
.bar_label
添加注释- 有关与相关的其他链接和选项,请参阅此答案
.bar_label
- 有关与相关的其他链接和选项,请参阅此答案
- 堆积条形图分别根据列和行的顺序从左到右和从下到上的顺序绘制。
- 由于
'Positive'
是列索引 2,我们只需要标签i == 2
- 由于
- 测试
pandas 1.3.0
并要求matplotlib >=3.4.2
和python >=3.8
- 的列表推导式
labels
使用赋值表达式 ,:=
它只能从python 3.8
labels = [f'{v.get_height():.0f}' if ((v.get_height()) > 0) and (i == 2) else '' for v in c]
是没有的选项:=
.bar_label
只能从matplotlib 3.4.2
- 这个答案显示了如何为
matplotlib <3.4.2
- 这个答案显示了如何为
- 的列表推导式
import pandas as pd
import numpy as np # used for nan
# test dataframe
data = {'Date':['2021-07-18','2021-07-19','2021-07-20','2021-07-21','2021-07-22','2021-07-23'],
'Invalid':[np.nan, 1, 1, np.nan, np.nan, np.nan],
'Negative':[23, 24, 17, 24, 20, 23],
'Positive':[np.nan, 1, 1, 1, np.nan, 1]}
df = pd.DataFrame(data)
# convert the Date column to a datetime format and use the dt accessor to get only the date component
df.Date = pd.to_datetime(df.Date).dt.date
# set Date as index
df.set_index('Date', inplace=True)
# create multi-index column to match OP image
top = ['Size']
current = df.columns
df.columns = pd.MultiIndex.from_product([top, current], names=['', 'Result'])
# display(df)
Size
Result Invalid Negative Positive
Date
2021-07-18 NaN 23 NaN
2021-07-19 1.0 24 1.0
2021-07-20 1.0 17 1.0
2021-07-21 NaN 24 1.0
2021-07-22 NaN 20 NaN
2021-07-23 NaN 23 1.0
# reset the top index to a column
df = df.stack(level=0).rename_axis(['Date', 'Size']).reset_index(level=1)
# if there are many top levels that are reset as a column, then select the data to be plotted
sel = df[df.Size.eq('Size')]
# plot
ax = sel.iloc[:, 1:].plot(kind='bar', stacked=True, figsize=(20, 5), title='Total Test Count vs Dates', color=['blue','green','red'])
# add annotations
for i, c in enumerate(ax.containers):
# format the labels
labels = [f'{w:.0f}' if ((w := v.get_height()) > 0) and (i == 2) else '' for v in c]
# annotate with custom labels
ax.bar_label(c, labels=labels, label_type='center', fontsize=10)
# pad the spacing between the number and the edge of the figure
ax.margins(y=0.1)
推荐阅读
- java - 如何从 Java 应用程序启用 https
- c# - 主菜单的设置菜单未在暂停菜单的设置菜单中更新。统一 C#
- python - 我正在尝试打印包含带有换行符的字符串的字典,但打印的是“\n”而不是换行符
- vue.js - 为什么我的 Quasar Android 应用程序没有更新?
- php - 如何打开放置在iframe html中直接访问阻止目录中的pdf文件
- java - SpringMVC 无法将实体写入 json
- appium - 为什么 MoveToElement 没有响应
- http-headers - 如何从 Content-Disposition 修改 HTTP 响应标头:收到 API 响应后附加到内联
- azure - 以编程方式获取 ADF 管道消耗报告
- docker - 运行 eureka 客户端服务时出现关于请求执行错误的错误