python - 如何用聚合值注释 seaborn barplot
问题描述
如何修改以下代码以在条形图的每个条形上显示平均值以及不同的误差条?
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("white")
a,b,c,d = [],[],[],[]
for i in range(1,5):
np.random.seed(i)
a.append(np.random.uniform(35,55))
b.append(np.random.uniform(40,70))
c.append(np.random.uniform(63,85))
d.append(np.random.uniform(59,80))
data_df =pd.DataFrame({'stages':[1,2,3,4],'S1':a,'S2':b,'S3':c,'S4':d})
print("Delay:")
display(data_df)
S1 S2 S3 S4
0 43.340440 61.609735 63.002516 65.348984
1 43.719898 40.777787 75.092575 68.141770
2 46.015958 61.244435 69.399904 69.727380
3 54.340597 56.416967 84.399056 74.011136
meansd_df=data_df.describe().loc[['mean', 'std'],:].drop('stages', axis = 1)
display(meansd_df)
sns.set()
sns.set_style('darkgrid',{"axes.facecolor": ".92"}) # (1)
sns.set_context('notebook')
fig, ax = plt.subplots(figsize = (8,6))
x = meansd_df.columns
y = meansd_df.loc['mean',:]
yerr = meansd_df.loc['std',:]
plt.xlabel("Time", size=14)
plt.ylim(-0.3, 100)
width = 0.45
for i, j,k in zip(x,y,yerr): # (2)
ax.bar(i,j, width, yerr = k, edgecolor = "black",
error_kw=dict(lw=1, capsize=8, capthick=1)) # (3)
ax.set(ylabel = 'Delay')
from matplotlib import ticker
ax.yaxis.set_major_locator(ticker.MultipleLocator(10))
plt.savefig("Over.png", dpi=300, bbox_inches='tight')
解决方案
- 给定示例数据,对于
seaborn.barplot
带有上限的误差线,data_df
必须从宽格式转换为整洁(长)格式,这可以通过pandas.DataFrame.stack
或pandas.DataFrame.melt
- 同样重要的是要记住,条形图仅显示平均值(或其他估计值)
示例数据和 DataFrame
.iloc[:, 1:]
用于跳过'stages'
列索引 0 处的列。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# given data_df from the OP, select the columns except stage and reshape to long format
df = data_df.iloc[:, 1:].melt(var_name='set', value_name='val')
# display(df.head())
set val
0 S1 43.340440
1 S1 43.719898
2 S1 46.015958
3 S1 54.340597
4 S2 61.609735
更新至matplotlib v3.4.2
- 利用
matplotlib.pyplot.bar_label
- 有关其他格式选项,请参阅matplotlib:条形标签演示页面。
- 可以使用
fmt
参数进行一些格式化,但应该使用labels
参数进行更复杂的格式化,如底部演示示例和如何向条形图添加多个注释中所示。
- 可以使用
- 经测试
seaborn v0.11.1
,matplotlib
用作绘图引擎。
fig, ax = plt.subplots(figsize=(8, 6))
# add the plot
sns.barplot(x='set', y='val', data=df, capsize=0.2, ax=ax)
# add the annotation
ax.bar_label(ax.containers[-1], fmt='Mean:\n%.2f', label_type='center')
ax.set(ylabel='Mean Time')
plt.show()
注释资源 - 来自matplotlib v3.4.2
- 在 matplotlib 条形图上添加值标签
- 如何注释堆积条形图的每个部分
- 带有居中标签的堆积条形图
- 如何在 seaborn barplot 中绘制和注释多个数据列
- matplotlib 中的堆栈条图并为每个部分添加标签
- 如何向条形图添加多个注释
- 如何绘制和注释分组条形图
情节与seaborn.barplot
- 使用
matplotlib
3.4.2 之前的版本 - 参数的默认
estimator
值为mean
,因此条形的高度是组的平均值。 - 条形高度是从
p
with中提取的.get_height
,可用于对条形进行注释。
fig, ax = plt.subplots(figsize=(8, 6))
sns.barplot(x='set', y='val', data=df, capsize=0.2, ax=ax)
# show the mean
for p in ax.patches:
h, w, x = p.get_height(), p.get_width(), p.get_x()
xy = (x + w / 2., h / 2)
text = f'Mean:\n{h:0.2f}'
ax.annotate(text=text, xy=xy, ha='center', va='center')
ax.set(xlabel='Delay', ylabel='Time')
plt.show()
推荐阅读
- android - 如何修复反应原生android中找不到的资源
- c# - 使用线程填充 TreeGridVew
- python - Python不转换日期
- angular - core.js:6014 错误错误:未捕获(承诺):错误:无法匹配任何路由。网址段:'qa'
- html - 使用垫子按钮以角度构建导航栏
- asciidoc - asciidoc 中的菜单
- reactjs - 使用 Enzyme Mount 测试包含 Child React Redux 组件的 React Parent 时出错
- python - 多级json数组中的Python不可散列类型'dict'
- javascript - 为什么将 window.location.hostname 传递给此条件语句会导致跨域错误?
- python - 在 mkdocs 中添加自定义元数据