You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Matplotlib分组柱状图添加误差棒?解决维度不匹配报错

解决Pandas分组柱状图yerr形状不匹配的报错问题

问题场景

分析田间试验蚯蚓计数数据,变量包含试验地/对照地、采集年份、种植作物、蚯蚓数量。使用groupby()按年份、场地类型、作物分组后绘制柱状图,添加标准差作为误差棒时触发报错:

ValueError: 'yerr' (shape: (8,)) must be a scalar or a 1D or (2, n) array-like whose shape matches 'y' (shape: (4,))

报错原因

你的groupby+unstack()操作后,生成的绘图数据结构是4行(年份+场地类型的组合)×2列(两种作物),即y轴数据形状为(4,2)。但你传入的yerr是一维列表(8个元素),形状(8,)与y轴数据不匹配——Pandas要求误差棒数组的形状必须和绘图的y数据完全对应,每个柱子对应一个误差值。

修复步骤

  1. 重新整理yerr,使其形状与分组后的数据结构一致:将误差值按「年份+场地类型」的分组,分别对应Maize和Rapeseed的误差,组成二维数组。
  2. 确保yerr的顺序与分组后DataFrame的列(作物)和行(年份+场地)顺序完全匹配。

完整修复代码

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

data = {"Style": ["Experiment","Reference", "Experiment", "Reference", "Experiment","Reference",
                  "Experiment", "Reference"],
        "Year": ["2021", "2021","2022","2022", "2021","2021", "2022","2022"],
        "Crop": ["Rapeseed", "Rapeseed", "Rapeseed", "Rapeseed",
                 "Maize", "Maize", "Maize", "Maize"],
        "Earthworms": [55, 2, 2,6,0,1,7,22]
       }

df = pd.DataFrame(data)

# 设置绘图属性
fig, ax = plt.subplots(figsize=(15,7))
colors = {"Maize": "#de8f05", "Rapeseed":"#d7bb19"}         

# 重新整理yerr:按[Maize误差, Rapeseed误差]的顺序,对应每一行(年份+场地)
# 顺序匹配分组后的行:2021-Experiment、2021-Reference、2022-Experiment、2022-Reference
yerr = [
    [0, 10.6926766215636],       # 2021-Experiment的Maize、Rapeseed误差
    [0.707106781186548, 1.4142135623731],  # 2021-Reference的误差
    [2.857738033, 0.577350269189626],       # 2022-Experiment的误差
    [4.43471156521669, 1.414213562]         # 2022-Reference的误差
]

# 分组并绘图:先分组求和,再unstack展开作物列,传入匹配形状的yerr
grouped_df = df.groupby(["Year", "Style", "Crop"])["Earthworms"].sum().unstack()
grouped_df.plot.bar(ax=ax, color=colors, yerr=yerr)

# 设置标签、坐标轴等样式
plt.ylabel("N", size=13, labelpad=10)
plt.yticks(fontsize=12)
plt.xticks(fontsize=12)
ax.set(xlabel=None)

plt.ylim(0,60)    
ax.spines.right.set_visible(False)
ax.spines.top.set_visible(False)
ax.margins(0.2,0)

plt.show()

额外优化建议

手动输入误差值容易出错,可直接通过Pandas分组计算标准差:

# 替换手动yerr,用groupby同时计算总和与标准差
grouped_stats = df.groupby(["Year", "Style", "Crop"])["Earthworms"].agg(['sum', 'std']).unstack()
# 用计算出的sum作为y值,std作为误差棒
grouped_stats['sum'].plot.bar(ax=ax, color=colors, yerr=grouped_stats['std'])

内容的提问来源于stack exchange,提问作者Laura

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 23:44:51