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

Matplotlib绘制带误差棒条形图 如何显示y轴负半轴适配RectangleSelector

问题说明

我已经成功绘制各年度数据分布均值的条形图,附带95% CI置信区间标准误差棒。为了后续使用RectangleSelector矩形选择器,需要同时显示y轴的负半轴部分。

原有代码
%matplotlib qt
from matplotlib.widgets import RectangleSelector
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import math

np.random.seed(12345)
df = pd.DataFrame([np.random.normal(32000,200000,3650), 
                    np.random.normal(43000,100000,3650), 
                    np.random.normal(43500,140000,3650), 
                    np.random.normal(48000,70000,3650)], 
                  index=[1992,1993,1994,1995])

mean = []
ci95 = []
for i in range(len(df)):
    globals()['avg%s' % (i+92)] = np.mean(df.iloc[i])
    globals()['semci%s' % (i+92)] = np.std(df.iloc[i])*1.96/math.sqrt(len(df.iloc[i]))
    mean.append(globals()['avg%s' % (i+92)])
    ci95.append(globals()['semci%s' % (i+92)])

year = np.array(['1992','1993','1994','1995'])
x_pos = np.arange(len(year))

def line_select_callback(eclick, erelease):
    'eclick and erelease are the press and release events'
    global x1, x2, y1, y2
    x1, y1 = eclick.xdata, eclick.ydata
    x2, y2 = erelease.xdata, erelease.ydata
    print("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2))
    probs = []
    for i in range(len(df)):
        globals()['btw%s' % (i+92)] = 0 
        for j in range(len(df.iloc[i])): 
            if (df.iloc[i,j] > y1) & (df.iloc[i,j] < y2):
                globals()['btw%s' % (i+92)] += 1 
        globals()['probs%s' % (i+92)] = globals()['btw%s' % (i+92)]/len(df.iloc[i])
        probs.append(globals()['probs%s' % (i+92)])
        
    my_cm = plt.get_cmap("Greens")
    ax.bar(x_pos, mean, yerr=ci95, align='center', alpha=0.5, ecolor='black', capsize=10, color = my_cm(np.array(probs)))
    ax.set_ylabel('')
    ax.set_xticks(x_pos)
    ax.set_xticklabels(year)
    ax.set_title('Assignment 3')
    ax.yaxis.grid(True)

def toggle_selector(event):
    print(' Key pressed.')
    if event.key in ['Q', 'q'] and toggle_selector.RS.active:
        print(' RectangleSelector deactivated.')
        toggle_selector.RS.set_active(False)
    if event.key in ['A', 'a'] and not toggle_selector.RS.active:
        print(' RectangleSelector activated.')
        toggle_selector.RS.set_active(True)

fig, ax = plt.subplots()
ax.bar(x_pos, mean, yerr=ci95, align='center', alpha=0.5, ecolor='black', capsize=10)
ax.set_ylabel('')
ax.set_xticks(x_pos)
ax.set_xticklabels(year)
ax.set_title('Assignment 3')
ax.yaxis.grid(True)

print("\n      click  -->  release")

toggle_selector.RS = RectangleSelector(ax, line_select_callback,
                                       drawtype='box', useblit=False,
                                       button=[1, 3],
                                       minspanx=5, minspany=5,
                                       spancoords='pixels',
                                       interactive=True)


plt.connect('key_press_event', toggle_selector)
plt.show()
解决方法

在两个位置新增y轴范围设置代码即可实现负半轴显示:

  • 初始化绘制条形图后添加ax.set_ylim(bottom=-20000),可根据需要调整bottom的数值,控制负半轴的显示长度
  • 回调函数line_select_callback中每次重绘条形图后,也要添加同样的y轴范围设置代码,避免重绘后y轴自动回弹为默认范围

修改后的核心代码示例

初始化绘图部分

fig, ax = plt.subplots()
ax.bar(x_pos, mean, yerr=ci95, align='center', alpha=0.5, ecolor='black', capsize=10)
ax.set_ylim(bottom=-20000) # 新增行
ax.set_ylabel('')
ax.set_xticks(x_pos)
ax.set_xticklabels(year)
ax.set_title('Assignment 3')
ax.yaxis.grid(True)

回调函数重绘部分

my_cm = plt.get_cmap("Greens")
ax.bar(x_pos, mean, yerr=ci95, align='center', alpha=0.5, ecolor='black', capsize=10, color = my_cm(np.array(probs)))
ax.set_ylim(bottom=-20000) # 新增行
ax.set_ylabel('')
ax.set_xticks(x_pos)
ax.set_xticklabels(year)
ax.set_title('Assignment 3')
ax.yaxis.grid(True)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:24:05