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

如何在Matplotlib中调整分组柱状图的组间间距(不改变柱宽)

问题描述
  • 分析田间实验蚯蚓数量数据,变量包含场地类型(实验场地/对照场地)、数据收集年份、种植作物、蚯蚓数量
  • 通过groupby()按场地类型、年份、作物对蚯蚓数量分组,绘制柱状图
  • 需求:不改变柱宽的前提下增大组间间距
  • 遇到的问题:
    • 尝试调整时触发错误:TypeError: bar() missing 1 required positional argument: 'height'
    • 手动定义height参数后,出现蓝色大柱覆盖其他分组柱的异常
原代码
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)

#Set graph properties
fig, ax = plt.subplots(figsize=(15,7))
colors = {"Maize": "#de8f05", "Rapeseed":"#d7bb19"}         
labels = list(colors.keys())


#Create yerr variable
yerr = [10.6926766215636, 1.4142135623731, 0.577350269189626,1.414213562, 0,
       0.707106781186548, 2.857738033, 4.43471156521669]

yerr = np.array(yerr).reshape(2,4)

#Groupby Year, Patchstyle, Crop (ind. variables), EW_num (dep. variable)
df = df.groupby(["Year", "Style", "Crop"])["Earthworms"].sum().unstack().plot.bar(ax=ax, color=colors,     yerr=yerr, width=0.9)


#Assign labels, axis ticks + limit, hide spines  

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)

#Create space between two groups of bars
#n_groups = 2
#index = np.arange(n_groups)

#ax.bar(index, height)
解决方案

直接用pandas的plot.bar()自动绘图无法精准控制组间距,需改用matplotlib手动计算柱子位置来实现需求:

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)

# 分组汇总数据,确保顺序对应
grouped = df.groupby(["Year", "Style", "Crop"])["Earthworms"].sum().unstack()
# 重新整理误差数据,匹配分组后的数值顺序
yerr = np.array([10.6926766215636, 0, 1.4142135623731, 0.707106781186548,
                 0.577350269189626, 2.857738033, 1.414213562, 4.43471156521669]).reshape(4, 2)

# 设置绘图参数
fig, ax = plt.subplots(figsize=(15,7))
colors = {"Maize": "#de8f05", "Rapeseed":"#d7bb19"}
bar_width = 0.4  # 单根柱子宽度,保持原需求不改变
group_gap = 0.8  # 组间空隙,调整此值控制间距大小

# 获取分组标签和基础x轴位置
x_labels = [f"{year}\n{style}" for year, style in grouped.index]
n_groups = len(x_labels)
# 通过扩展x轴索引实现组间间距
x = np.arange(n_groups) * (1 + group_gap)

# 分作物绘制柱子
for i, crop in enumerate(grouped.columns):
    # 计算同组内不同作物柱子的错开位置
    ax.bar(x + (i - 0.5)*bar_width, grouped[crop], width=bar_width, 
           color=colors[crop], label=crop, yerr=yerr[:, i])

# 设置轴样式
ax.set_ylabel("N", size=13, labelpad=10)
ax.set_xticks(x)
ax.set_xticklabels(x_labels, fontsize=12)
ax.tick_params(axis='y', labelsize=12)
ax.set(xlabel=None)
ax.set_ylim(0,60)
ax.spines.right.set_visible(False)
ax.spines.top.set_visible(False)
ax.legend(title="Crop")

plt.tight_layout()
plt.show()

关键说明

  1. 放弃pandas自动绘图逻辑,改用matplotlib手动绘制,实现对柱子位置的精准控制
  2. 通过np.arange(n_groups) * (1 + group_gap)扩展x轴索引,直接增大组间间距,且不改变柱宽
  3. 重新整理误差数据顺序,确保误差线与对应柱子匹配,避免错位
  4. 用x + (i - 0.5)*bar_width计算同组内不同作物柱子的位置,实现并排效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:32:49