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

matplotlib 2x2共享轴子图末图无数据破坏对数刻度问题求解

问题原因

你开启了全局y轴共享,但仅给有数据的子图设置了对数刻度,空数据子图既没有设置对数刻度,也没有主动限制y轴范围。matplotlib会自动同步所有共享轴的刻度规则和范围,最后绘制的空子图默认使用线性刻度、y轴范围为[0,1],和前面子图的对数刻度范围冲突,最终导致全局刻度异常。


修复方案1:提前统一配置刻度与范围(推荐)

提前给所有子图统一设置对数刻度,再根据有效数据的取值范围固定全局y轴上下限即可,既保留所有子图结构,也不会破坏刻度规则。
修复后代码如下:

import matplotlib.pyplot as plt

n_plots_per_fig = 4
nrows = 2
ncols = 2

fig, axs = plt.subplots(nrows, ncols, sharex="all", sharey="all", figsize=(8, 6))
axs = axs.ravel()

# 提前统一设置所有子图的y轴为对数刻度
for ax in axs:
    ax.set_yscale("log")

# 统计所有有效数据的y轴范围,也可根据业务场景直接预设合理范围
y_min, y_max = float("inf"), float("-inf")
valid_data_list = []

# 先绘制所有有数据的子图,统计取值范围
for i, ax in enumerate(axs):
    x = [1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
    bins = 3
    ax.set_title(str(i), fontsize="medium")
    # 跳过空数据子图,后续统一处理
    if i == n_plots_per_fig - 1:
        valid_data_list.append(False)
        continue
    valid_data_list.append(True)
    if x:
        n, _, _ = ax.hist(x, bins=bins)
        # 过滤0值避免对数刻度报错,更新范围
        valid_n = n[n > 0]
        if len(valid_n) > 0:
            y_min = min(y_min, valid_n.min())
            y_max = max(y_max, valid_n.max())

# 统一设置全局y轴范围,留适当边距
for ax in axs:
    ax.set_ylim(y_min * 0.5, y_max * 2)

# 最后处理空数据子图,添加NA文本
for i, ax in enumerate(axs):
    if not valid_data_list[i]:
        ax.text(0.5, 0.5, 'NA', ha='center', va='center', transform=ax.transAxes)

plt.show()

修复方案2:解除空数据子图的共享关系

如果需要不同子图使用不同刻度规则,可以在绘制空数据子图前就解除其y轴共享,避免影响全局刻度,只需在空数据处理分支添加两行代码即可:

# 仅移除当前空子图的y轴共享关系
ax.get_shared_y_axes().remove(ax)
# 隐藏空子图的刻度,避免显示异常
ax.set_yticks([])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 23:15:01