当前位置:首页>python>用Python做科研级画图——分组对比

用Python做科研级画图——分组对比

  • 2026-09-10 23:12:13
用Python做科研级画图——分组对比

大家好,我是你们的小帅学长。

上一期我们讲了排序 + 水平条,是单维对比的最稳解法。但科研里真正常见的场景往往是不只是“谁更高”,而是“在不同条件下,谁更高?”。

例如:不同模型 × 不同数据集

不同处理组 × 不同指标

不同年份 × 不同区域

这时候,如果你还用单一柱状图硬挤,图会迅速变乱。

解决方法其实很清晰:一是 分组柱(Grouped Bar)——同图对比;二是分面图(Facet / Small multiples)——分图对比。

这一篇,我想要讲清楚:什么时候用分组柱?什么时候用分面?怎么画得像论文?

01.分组柱:同一画布上的“并列对比”

适合场景:

组别不多(2–4 组)

每组类别也不多(≤6)

你希望读者直接横向比较差异

例如:3 个模型在 4 个数据集上的表现。

优点:信息密集、视觉紧凑、对比直接

缺点:组别一多就开始拥挤、颜色多了就开始难区分

一句话判断:

维度不多 → 分组柱最直接

维度变多 → 分面更清晰

02.分面:让每个组都有自己的空间

分面本质上是把“颜色区分”改成“空间区分”。而空间分离的认知负担远低于颜色识别。

适合场景:

组别多(>4)

你希望每组有完整 y 轴

你希望趋势或结构更清楚

分面最大的优点是 每个子图都有自己的基线,不会互相干扰。

03.一个核心原则:不要同时增加颜色 + 组别 + 类别

一张图里最多控制 2 个视觉变量。超过 2 个维度,就分面。

科研图不是拼信息量,是拼可读性。

04.分组柱

import osimport numpy as npimport matplotlib as mplimport matplotlib.pyplot as pltfrom matplotlib import font_manager as fmfrom matplotlib.ticker import MaxNLocator, FormatStrFormatter# == 字体设置 ==win_fonts = r"C:\Windows\Fonts"for p in [    os.path.join(win_fonts, "times.ttf"),    os.path.join(win_fonts, "timesbd.ttf"),    os.path.join(win_fonts, "timesi.ttf"),    os.path.join(win_fonts, "simsun.ttc"),]:   if os.path.exists(p):        try:            fm.fontManager.addfont(p)        except Exception:            passmpl.rcParams["font.family"] = ["Times New Roman", "SimSun"]mpl.rcParams["axes.unicode_minus"] = FalseOUT_DIR = r"D:\py_figs_grouped"os.makedirs(OUT_DIR, exist_ok=True)# == 示例数据 ==categories = ["Dataset A / 数据集A",               "Dataset B / 数据集B",               "Dataset C / 数据集C"]model1 = np.array([0.91, 0.87, 0.89])model2 = np.array([0.88, 0.85, 0.86])model3 = np.array([0.84, 0.83, 0.82])x = np.arange(len(categories))width = 0.25fig, ax = plt.subplots(figsize=(7.2, 4.2))ax.bar(x - width, model1, width, label="Model 1 / 模型1")ax.bar(x,         model2, width, label="Model 2 / 模型2")ax.bar(x + width, model3, width, label="Model 3 / 模型3")ax.set_xticks(x)ax.set_xticklabels(categories, fontsize=11)ax.set_ylabel("Accuracy / 准确率", fontsize=12)ax.set_title("分组对比:不同模型在各数据集表现", fontsize=14)ax.set_ylim(bottom=0)ax.yaxis.set_major_locator(MaxNLocator(nbins=6))ax.yaxis.set_major_formatter(FormatStrFormatter("%.2f"))ax.legend(frameon=False)out_path = os.path.join(OUT_DIR, "grouped_bar_basic.jpg")fig.savefig(out_path, dpi=300, bbox_inches="tight", pad_inches=0.05)plt.close(fig)print("Saved:", out_path)

05.分面

当组别多时,用分面更稳:

# ===== 分面示例 =====fig, axes = plt.subplots(1, 3, figsize=(9, 3.8), sharey=True)models = [model1, model2, model3]titles = ["Model 1 / 模型1", "Model 2 / 模型2", "Model 3 / 模型3"]for ax, data, title in zip(axes, models, titles):    ax.bar(categories, data)    ax.set_title(title, fontsize=12)    ax.set_ylim(bottom=0)    ax.tick_params(axis='x', rotation=20)    ax.yaxis.set_major_locator(MaxNLocator(nbins=5))axes[0].set_ylabel("Accuracy / 准确率", fontsize=12)fig.suptitle("分面表达:空间分离优于颜色堆叠", fontsize=14)fig.savefig(os.path.join(OUT_DIR, "facet_bar_basic.jpg"),            dpi=300, bbox_inches="tight", pad_inches=0.05)plt.close(fig)

06.分组柱 vs 分面

情况
推荐
组别≤ 3,类别 ≤ 5
分组柱
组别≥ 4
分面
强调直接对比
分组柱
强调结构或趋势
分面
画面已经拥挤
分面

分组柱适合“并排比较”,分面适合“分开表达”;当图开始变乱时,不是你数据多了,而是你该换布局了。

下一篇我们聊一个经常被误用的图形:《堆叠柱的误区》。堆叠柱看起来信息量大,但它和堆叠面积一样,常常会让比较变得困难——下一篇我会教你什么时候该用、什么时候一定不要用,以及更稳的替代方案。

——期待你的关注——

 往期内容:

用Python做科研级画图——柱状图基础

用Python做科研级画图——折线图基础模板

用Python做科研级画图——论文级排版检查清单(Checklist)

用Python做科研级画图——配色与色带:连续离散怎么选

用Python做科研级画图——标注与强调:箭头/框/高亮怎么用

用Python做科研级画图——图例与刻度:让图“少而清楚”

最新文章

随机文章