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

绘制含极端正负值的柱状图问题求助

解决方案

针对你的数据(包含极端负数值和小正数),以下几种方法可以绘制出比例合理的柱状图,避免log变换无法处理负数的问题:

1. 对称对数刻度(symlog)

这是最直接的方法,matplotlib的symlog刻度支持正负数值,会在0附近使用线性刻度,远离0的区域用对数刻度,既能压缩极端值的跨度,又能保留小数值的细节。

代码示例

import pandas as pd
import matplotlib.pyplot as plt

# 构建DataFrame
data = {
    'Head': ['A', 'B', 'C'],
    'Values': [-1000000000, -650000, 9500]
}
df = pd.DataFrame(data)

# 绘制柱状图
plt.figure(figsize=(8, 5))
bars = plt.bar(df['Head'], df['Values'])
plt.yscale('symlog')
plt.ylabel('数值(对称对数刻度)')
plt.title('带对称对数刻度的柱状图')

# 为每个柱子标注具体数值
for bar in bars:
    height = bar.get_height()
    plt.text(bar.get_x() + bar.get_width()/2., height,
             f'{int(height):,}',
             ha='center', va='bottom' if height > 0 else 'top')

plt.tight_layout()
plt.show()

2. 截断Y轴(分轴展示)

如果需要保留线性刻度的直观性,可以将Y轴拆分为上下两部分,分别展示极端值和小范围数值,同时用截断标记明确提示轴的断裂。

代码示例

import pandas as pd
import matplotlib.pyplot as plt

data = {
    'Head': ['A', 'B', 'C'],
    'Values': [-1000000000, -650000, 9500]
}
df = pd.DataFrame(data)

# 创建上下两个子图
fig, (ax_top, ax_bottom) = plt.subplots(2, 1, figsize=(8, 7), gridspec_kw={'height_ratios': [1, 4]})

# 上方子图展示极端负数值
ax_top.bar(df['Head'], df['Values'])
ax_top.set_ylim(-1.1e9, -6e5)
ax_top.tick_params(labelbottom=False)  # 隐藏下方刻度,避免重复
ax_top.set_ylabel('极端数值')

# 下方子图展示小范围数值
ax_bottom.bar(df['Head'], df['Values'])
ax_bottom.set_ylim(-7e5, 1.1e4)
ax_bottom.set_ylabel('小范围数值')
ax_bottom.set_xlabel('类别')

# 添加轴截断标记
d = 0.015  # 标记线长度
kwargs = dict(transform=ax_top.transAxes, color='black', clip_on=False)
ax_top.plot((-d, +d), (-d, +d), **kwargs)
ax_top.plot((1 - d, 1 + d), (-d, +d), **kwargs)

kwargs.update(transform=ax_bottom.transAxes)
ax_bottom.plot((-d, +d), (1 - d, 1 + d), **kwargs)
ax_bottom.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs)

# 标注每个柱子的数值
for ax in [ax_top, ax_bottom]:
    for bar in ax.patches:
        height = bar.get_height()
        ax.text(bar.get_x() + bar.get_width()/2., height,
                f'{int(height):,}',
                ha='center', va='bottom' if height > 0 else 'top')

plt.suptitle('截断Y轴的柱状图')
plt.tight_layout()
plt.show()

3. 突出相对差异(转换数据)

如果你的核心需求是对比各数值之间的相对大小,而非绝对数值,可以将数据转换为与基准值(比如C的数值)的比值,或者展示绝对值的对数并标注正负符号:

代码示例(与C的比值)

import pandas as pd
import matplotlib.pyplot as plt

data = {
    'Head': ['A', 'B', 'C'],
    'Values': [-1000000000, -650000, 9500]
}
df = pd.DataFrame(data)

# 计算与C的比值
df['Ratio_to_C'] = df['Values'] / df.loc[df['Head'] == 'C', 'Values'].values[0]

plt.figure(figsize=(8, 5))
bars = plt.bar(df['Head'], df['Ratio_to_C'])
plt.ylabel('与C的比值')
plt.title('各数值与C的相对比值柱状图')

for bar in bars:
    height = bar.get_height()
    plt.text(bar.get_x() + bar.get_width()/2., height,
             f'{height:.1f}',
             ha='center', va='bottom' if height > 0 else 'top')

plt.tight_layout()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 15:52:42