资讯动态

Matplotlib科研绘图实战:阻尼、XRD、函数与统计拟合全解析

发布时间:2026/10/13 21:10:22 来源:尧图企业网站定制
做科研数据分析的人电脑里八成装着一个 matplotlib。阻尼衰减曲线、XRD 衍射谱、三角函数、超越函数、正态分布随机数与插值多项式——这几个主题看着零散其实是把物理模拟、实验可视化、数学画图、统计拟合四大类最常见的绘图需求都过了一遍。我写这篇东西目标很直接把每个案例从头到尾走一遍给出能直接跑的代码再把参数为什么这么选、哪些地方容易翻车讲清楚。新手可以照着敲一遍建立手感有经验的朋友可以直接看各节末尾的避坑心得。默认你已经装好了 Python 3.8 以上的环境没有的话装一个 Anaconda 是最省事的路径下面提到的所有库都通过 pip 安装即可。1. 案例梳理与作图环境准备1.1 五个案例背后的共同需求先说结论标题这五项看起来是五个独立的 demo实际上是在回答一个问题——用 matplotlib 把不同类型的曲线画到能发表、能汇报、能让人一眼看懂的程度需要具备哪些基本功。阻尼衰减曲线属于物理过程模拟特点是函数值随时间呈指数包络振荡画图重点在包络线和振荡周期的平衡。XRD 属于实验数据绘图数据是一堆离散的二维数值画图重点在谱峰定位、背景处理和归一化。三角函数与超越函数属于数学函数可视化画图重点在定义域、周期和坐标刻度。正态分布随机数加插值多项式则是典型的统计数据分析重点是随机数生成、直方图统计、理论分布曲线以及用多项式做连续化逼近。可以这样理解这几类需求的差异物理模拟类数据是公式算出来的关键在于参数物理意义是否合理实验数据类数据是仪器测出来的关键在于原始信息有没有被可视化过程扭曲数学函数类数据是纯数学表达式关键在于坐标轴刻度能否体现函数本质统计分布类数据是随机生成的关键在于样本量与拟合方法是否匹配。案例数据类型核心绘图难点典型应用场景阻尼衰减曲线公式生成包络线与周期匹配振动分析、电路瞬态、控制响应XRD数据绘图实验采集峰位标注与基线处理材料物相分析、组分鉴定三角函数绘图公式生成π刻度与渐近线处理信号分析、教学演示超越函数绘图公式生成定义域与坐标尺度增长模型、衰减模型、幂律验证正态分布插值随机采样拟合阶数选择与过拟合统计模拟、误差分析、概率建模1.2 环境配置与中文字体一次搞定代码执行依赖 numpy、matplotlib 和 scipy 三个库缺一不可。如果是干净环境直接pip install numpy matplotlib scipy装完之后先做一件事配置 matplotlib 支持中文显示。这个问题几乎所有人在第一次画图时都会遇到。matplotlib 默认字体不含中文字符图里一旦出现中文标签就是方块乱码。我习惯在脚本开头统一设置import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC] plt.rcParams[axes.unicode_minus] Falseaxes.unicode_minus这条很多人会漏掉它负责让负号正常显示。默认情况下坐标轴负号用的是 Unicode 减号当你把字体切换成中文字体后这个减号容易被渲染成方块。指定 False 后负号会用 ASCII 连字符问题立刻消失。这里多说一句如果只是写个人脚本我推荐把这段配置放到一个公共的plot_style.py里每次绘图脚本导入它即可。# plot_style.py import matplotlib.pyplot as plt def set_style(): plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, PingFang SC] plt.rcParams[axes.unicode_minus] False plt.rcParams[lines.linewidth] 1.5 plt.rcParams[font.size] 10 plt.rcParams[savefig.dpi] 300这样所有图表的风格、字体、默认配色都统一后期改样式只改一个文件。字体方面SimHei 在 Windows 和多数 Linux 上可用macOS 用 PingFang SC 更稳。按照我的经验宁可多写几个备选字体也不要只写一个——换机器跑脚本的时候这个细节能省不少事。2. 阻尼衰减曲线从振动方程到包络线2.1 物理背景与参数设定阻尼衰减曲线最典型的来源是一个带阻尼的弹簧振子系统。理想简谐振动不会衰减真实系统里总有阻力所以位移会一边振荡一边按指数规律衰减。位移随时间的表达式是x(t) A0 · exp(-δ·t) · cos(ωd·t φ)其中 A0 是初始振幅δ 是阻尼系数ωd 是阻尼振荡角频率φ 是初相位。这个公式有意思的地方在于它把衰减和振荡两个因素封装在一起。画图的时候如果不单独把包络线画出来读者往往看不出振荡在整体衰减一旦把 ±A0·exp(-δ·t) 两条包络虚线叠上去图像立刻有了层次物理含义也清晰了。选参数时我会先用物理直觉定而不是随手取。工程里常见的阻尼比在 0.05~0.5 之间对应 δ 值一般小于 1。我通常取 A01.0、δ0.3周期 T 取 2 秒这样前几个周期内能看到明显衰减又不至于还没振荡两个周期就衰减没了。时间序列从 0 到 12 秒取 1000 个点点之间的间隔约 0.012 秒余弦曲线足够平滑。如果你发现自己画的曲线有明显折角不是公式的问题是点数太少把点数从 1000 提到 3000 就好。2.2 绘图代码与细节下面的代码可以直接跑import numpy as np import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei] plt.rcParams[axes.unicode_minus] False A0 1.0 delta 0.3 T 2.0 omega_d 2 * np.pi / T phi 0.0 t np.linspace(0, 12, 1000) x A0 * np.exp(-delta * t) * np.cos(omega_d * t phi) env A0 * np.exp(-delta * t) plt.figure(figsize(8, 5)) plt.plot(t, x, label阻尼振荡曲线, lw1.6, color#2E86AB) plt.plot(t, env, ls--, color#888888, lw1.2, label包络线 ±A0·exp(-δt)) plt.plot(t, -env, ls--, color#888888, lw1.2) plt.xlabel(时间 t (s)) plt.ylabel(位移 x(t)) plt.xlim(0, 12) plt.ylim(-1.2, 1.2) plt.grid(alpha0.3) plt.legend(frameonFalse) plt.tight_layout() plt.show()几个值得说的点图例用了frameonFalse框线去掉以后图例跟图更融合ylim取 ±1.2 是给曲线留一点余量避免顶部和底部贴边tight_layout()是每次出图前必做的它会自动调整边距保证标签不被截断。包络线我只在第一条虚线上写了 label第二条纯视觉辅助没有 label所以图例里不会出现两行一模一样的“包络线”干净利落。另外振荡频率与衰减速度的匹配直接影响视觉效果。如果 ωd 太大同样时间范围内会画出一团密实的黑色什么都看不出来如果 ωd 太小整个图看起来像一条普通指数衰减曲线振荡特性又丢了。想让读者一眼看出“这是衰减振荡”我的经验是让前三个周期内振幅降到初始值的 40% 左右这个比例对应的画面既平衡又直观。2.3 实操心得这类曲线最容易翻车的地方在参数选择。把 δ 从 0.3 改成 1.5曲线会迅速衰减振荡只出现一两个周期改成 0.05衰减很慢画满整个横坐标范围它还在高低起伏。这两种形态没有对错取决于你想表达什么物理场景但作为一张图要让读者一眼看到“衰减”这个核心信息δ 取 0.2~0.5 区间的视觉表现最理想。还有一个实用技巧如果原始数据长数千个点振荡密集区重叠严重不要整段全画出来直接用plt.xlim把尾部裁掉只看前几个周期。我曾给某个项目画瞬态响应曲线原始数据好几千个点全部画出后振荡部分被压缩成一条黑色带把横坐标裁到前 500 个点问题立刻解决坐标轴上的刻度也更稀疏、更易读。3. XRD数据绘图科研图谱的标准姿势3.1 XRD数据长什么样XRD 全称 X 射线衍射是材料分析里最常用的表征手段之一。它的原始数据本质上是两列数组横轴是衍射角 2θ单位是 degree纵轴是探测器记录的强度通常记作 a.u.即任意单位。不同晶面对应不同的衍射角所以谱图上会出现一组尖锐的峰峰的位置和强度对应材料的物相信息。实际拿到的数据文件格式很不统一有的第一行是标题有的第二行是采集参数有的列之间用逗号分隔有的用空格甚至制表符。我的习惯是统一用 numpy 的loadtxt读取配合skiprows跳过不需要的行data np.loadtxt(sample.xrd, skiprows2) theta data[:, 0] intensity data[:, 1]如果文件里夹杂了字符串行loadtxt会直接报错这种情况就改用np.genfromtxt或者用内置open逐行清洗一遍。第一次看到 XRD 数据被 \t 和空格混着分隔的时候可能有点头疼但只要记住读数据这步花十分钟做规范后面绘图至少省一小时。为了让大家在没有真实数据时也能跑通我下面的代码用模拟数据在若干角度位置叠加高斯峰再加一点随机噪声。真实场景里只要把 loadtxt 读取的两列替换进变量即可绘图逻辑完全不用改。3.2 绘制谱图与峰位标注import numpy as np import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei] plt.rcParams[axes.unicode_minus] False theta np.linspace(10, 80, 1000) peaks [] for center, amp, width in [(26.5, 1.0, 0.20), (38.2, 0.65, 0.25), (53.1, 0.40, 0.30), (64.2, 0.75, 0.22)]: peaks.append(amp * np.exp(-((theta - center) ** 2) / (2 * width ** 2))) intensity np.sum(peaks, axis0) 0.02 * np.random.rand(theta.size) plt.figure(figsize(9, 4.5)) plt.plot(theta, intensity, lw1.5, color#2E86AB) for p in [26.5, 38.2, 53.1, 64.2]: plt.axvline(xp, color#D64933, ls:, alpha0.6) plt.text(p, 0.18, f{p:.1f}°, hacenter, fontsize9, color#D64933) plt.xlabel(2θ (degree)) plt.ylabel(Intensity (a.u.)) plt.xlim(10, 80) plt.grid(alpha0.3) plt.tight_layout() plt.show()标注峰位时我没有手动一个个找坐标而是维护一个包含峰位的列表统一管理。这样后续需要重新标注、加标记、批量处理多个样品时只需要改列表内容。图中用axvline画竖向虚线加 text 角度标签红色辅助线与蓝色主谱线形成区分。text 的纵坐标 0.18 是我在这个模拟数据下的粗略估计如果某个峰特别低矮标签可能盖住峰本身实际画完以后需要肉眼看一遍逐个微调这个值。归一化和平滑也是 XRD 绘图里绕不开的操作。多个样品强度水平不一致时直接叠加会让低强度样品看起来像噪声正确的做法是归一化到最大强度intensity_norm intensity / intensity.max()数据噪声大、峰形不明显时可以使用 Savitzky-Golay 平滑但注意窗口不要太大过度平滑会让尖锐的衍射峰变钝反而丢失信息。3.3 多组图谱对比与出图设置材料研究里经常要对比不同条件下测得的几条 XRD 谱比如不同工艺温度下的产物。多谱叠加时最容易出现的问题是谱线互相遮挡下面的谱被上面的盖住。我的做法是给每条谱设置一个垂直偏移量让它们在纵轴上依次错开有点像地理图里的垂直分层。offsets [0.0, 0.8, 1.6, 2.4] labels [原始样品, 热处理样A, 热处理样B, 掺杂物样] for offset, label in zip(offsets, labels): plt.plot(theta, intensity_norm offset, lw1.2, labellabel)需要强调垂直偏移会改变数据原有的强度比例所以图里一定要注明“Intensity (a.u.)曲线已垂直偏移”避免误导读者。偏移量的取值以相邻曲线之间不重叠为宜我自己通常取最大强度的 0.8~1.2 倍。这种实验数据处理完最终大概率要放进论文或汇报里。我建议按两个方向保存plt.savefig(xrd_compare.pdf, dpi300, bbox_inchestight) plt.savefig(xrd_compare.png, dpi300, bbox_inchestight)PDF 是矢量格式插入论文或矢量汇报文件里不会模糊PNG 是位图适合网页和快速预览。bbox_inchestight的意思是按内容自动裁剪它和tight_layout()的区别是后者调整的是画布内布局前者调整的是最终输出范围。两个都用没问题但只选一个的话我选bbox_inchestight因为它对savefig生效对实际文件最立竿见影。4. 三角函数与超越函数把数学图像画准4.1 三角函数绘图的陷阱三角函数本身很简单但默认设置画出来会很难看。第一个陷阱是刻度如果直接用默认数值刻度x 轴上出现的是 0、2、4、6 这样的小数跟 sin 函数的 π 周期气质完全不符。标准做法是把刻度设在 π 的倍数上再用 LaTeX 风格的标签x np.linspace(-2*np.pi, 2*np.pi, 1000) fig, axes plt.subplots(2, 1, figsize(9, 6)) axes[0].plot(x, np.sin(x), labelsin(x), lw1.6) axes[1].plot(x, np.cos(x), labelcos(x), lw1.6, color#D64933) for ax in axes: ax.set_xticks([-2*np.pi, -np.pi, 0, np.pi, 2*np.pi]) ax.set_xticklabels([r$-2\pi$, r$-\pi$, 0, r$\pi$, r$2\pi$]) ax.set_ylim(-1.4, 1.4) ax.grid(alpha0.3) ax.legend(frameonFalse, locupper right) axes[0].set_title(sin(x)) axes[1].set_title(cos(x)) plt.tight_layout() plt.show()r$-\pi$这种原始字符串加数学环境是 matplotlib 显示数学符号的标准写法。比起把标签写成 -π用这种方式渲染出来的 π 看起来更像是印刷体不会出现字体怪异的问题。还有一个隐性细节np.linspace(-2π, 2π, 1000)包括两个端点所以画出来的 sin 和 cos 首尾刚好闭合这是对的。如果你不想画闭合周期可以让终点稍微差一点但一般没必要。tan 函数是三角函数绘图里的一个例外。它在 π/2 附近有渐近线按默认方式画会在渐近线附近拉出一条几乎垂直的长线特别难看。处理办法有两种一种是画完立刻限制plt.ylim(-10, 10)另一种是用 numpy 把超过阈值的值替换成 nan后者更彻底y np.tan(x) y[np.abs(y) 10] np.nannan 在绘图时会被自动忽略这样渐近线两侧的行为分别显示中间不会出现直上直下的连线。这两种办法我更推荐掩膜处理因为它保留的是真实数学行为只是丢弃了超出视野的部分。4.2 超越函数的定义域与坐标尺度超越函数是指数、对数、幂这类无法用代数多项式表示的函数。画超越函数十个人里八个会在定义域上翻车。对数函数要求 x 0所以x np.linspace(0, 5)会直接让对数产生警告因为第一个点是 0正确做法是从 0.01 或 0.1 开始。指数函数增长太快。假如在同一张图里同时画 exp(x) 和 log(x)线性坐标下 log 分量会被压成一条水平线什么都看不见。这时有两种应对一种是分开画在各自合适的区间另一种是用半对数坐标或双对数坐标。我不建议无脑用对数坐标只有在数据跨多个数量级时才需要。半对数坐标用plt.semilogy()双对数用plt.loglog()它们的参数和plot()完全一样只是坐标系不同x np.linspace(0.01, 5, 500) fig, axes plt.subplots(1, 3, figsize(12, 4)) axes[0].plot(x, np.exp(x), color#2E86AB) axes[1].semilogy(x, np.exp(x), color#D64933) axes[2].loglog(x, x**2, color#2E86AB) for i, title in enumerate([线性坐标, 半对数坐标, 双对数坐标]): axes[i].set_title(title) axes[i].grid(alpha0.3)幂函数 y x^2 在双对数坐标里呈现为一条直线这个特性在做数据分析时很有用——如果你怀疑某个变量关系是幂律分布画 loglog 图看是否为直线就能快速验证。我前阵子处理一组实验数据原始曲线在普通坐标下完全看不出规律换成半对数坐标后指数衰减阶段一目了然当场就把结论定了。这也是为什么科研绘图不能只学功能还得懂一点数学直觉。4.3 子图布局管理如果你要在一个图里同时展示多个函数plt.subplots是最好的工具。上面两个示例里我已经用了plt.subplots(2, 1)和plt.subplots(1, 3)这里补充一个细节子图之间经常共用横轴在 ax 上单独设置刻度会显得重复。可以只给最下面一行标 x 轴标签上面的子图用sharexTrue自动对齐fig, axes plt.subplots(2, 1, figsize(8, 6), sharexTrue) axes[0].plot(x, np.sin(x)) axes[0].set_ylabel(sin(x)) axes[1].plot(x, np.cos(x), color#D64933) axes[1].set_ylabel(cos(x)) axes[1].set_xlabel(x (rad))sharexTrue还有个好处缩放任意一个子图另一个会同步跟随交互式分析时非常顺手。初学的时候容易在每个子图里都写一遍 xticks、xlabel、legend代码又长又容易出错。我的习惯是全局统一的样式用循环处理只有各自不同的标签和曲线才单独写。5. 正态分布随机数与插值多项式拟合5.1 生成随机数与直方图正态分布随机数在统计模拟里最常用。制造一堆服从正态分布的样本点本身没什么难的关键在于怎么把分布形态直观地展示出来并且用数学工具把趋势提取成一条光滑曲线。import numpy as np import matplotlib.pyplot as plt from scipy.interpolate import CubicSpline plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei] plt.rcParams[axes.unicode_minus] False np.random.seed(42) samples np.random.normal(loc0.0, scale1.0, size2000) counts, bins, _ plt.hist(samples, bins40, densityTrue, alpha0.6, color#9ACDBA, label样本直方图) bin_centers (bins[:-1] bins[1:]) / 2np.random.seed(42)是固定随机种子。科研模拟里种子必须设否则每次运行结果都不一样图表没法复现这在论文审稿人眼里是硬伤。densityTrue表示把直方图的纵轴归一化成概率密度这样无论样本量是 2000 还是 20000直方图都能与理论概率密度曲线直接可比。bin 数量的选择也有讲究。样本量 2000、bins40 是我常用的组合平均每个 bin 里大约有 50 个样本直方图既能看到分布轮廓又不会因为随机波动而剧烈锯齿。样本量少的时候要减少 bin 数否则每个 bin 只有零星几个样本图形像梳子一样。5.2 叠加理论概率密度曲线标准正态分布的密度函数是f(x) (1 / sqrt(2π)) · exp(-x² / 2)直接用向量化运算画出来然后叠加到直方图上x_pdf np.linspace(-4, 4, 300) pdf (1 / np.sqrt(2 * np.pi)) * np.exp(-x_pdf ** 2 / 2) plt.plot(x_pdf, pdf, r-, lw2.0, label理论正态分布) plt.xlabel(样本值) plt.ylabel(概率密度) plt.legend(frameonFalse) plt.show()这一阶段图已经能说明问题了——样本分布与理论曲线的吻合程度由样本量和 bin 数量共同决定。样本太少直方图会像锯齿bin 太少细节又会被抹平。400 个样本配 30 个 bin是入门时比较稳妥的比例。如果你发现直方图整体高于理论曲线或者明显低于理论曲线多半是density没设置对或者样本的均值和标准差与你画理论曲线时用的参数不一致。5.3 插值多项式从离散点恢复连续趋势直方图的输出是一堆 bin 的计数本身就是离散台阶。如果我们希望得到一条平滑曲线有两条路可以走多项式拟合和插值。标题里说的“插值多项式”我的理解就是用多项式的思路去逼近直方图背后的分布形态。先看多项式拟合。np.polyfit是最直接的方式它返回多项式系数deg 7 coeffs np.polyfit(bin_centers, counts, deg) poly np.poly1d(coeffs) x_poly np.linspace(bin_centers[0], bin_centers[-1], 300) plt.plot(x_poly, poly(x_poly), g--, lw2.0, labelf{deg}次多项式拟合)这里有一个关键认知阶数不是越高越好。用 2 次多项式拟合得到的是抛物线完全没法表达正态分布的平坦峰顶用 20 次多项式曲线会在数据点之间剧烈震荡也就是过拟合。我实际测过这个场景7~9 次的拟合结果在视觉上最接近正态分布又不至于在边界处失控。过拟合的典型表现是曲线像“电波”一样上下跳动一旦看到这种形态第一反应就是降阶。再看插值。CubicSpline用分段三次多项式插值能保证曲线穿过所有数据点而且不会出现整体高阶多项式那样的边界振荡cs CubicSpline(bin_centers, counts) x_cs np.linspace(bin_centers[0], bin_centers[-1], 300) plt.plot(x_cs, cs(x_cs), b:, lw2.0, label三次样条插值)插值和拟合的区别可以理解为拟合不要求穿过所有点只要求整体误差最小插值必须穿过每一个观测点。数据噪声大时用插值会把噪声也“完美”地穿过去反而是拟合更能反映趋势。所以对直方图这种带随机波动的数据我更推荐多项式拟合如果是实验测得的平滑变化量需要曲线经过每一个测量点那就上样条插值。最后补一条经验多项式在数据点范围外的行为完全不可控。一旦你把拟合曲线的横坐标画到 bin 的范围之外曲线会瞬间冲向正负无穷。所以画拟合曲线时横坐标一定要限制在bin_centers[0]到bin_centers[-1]之间不要延伸到 -5 或 5。这个坑我在第一次画拟合曲线时踩过图里突然出现一条冲天的曲线排查了半天才发现是 x 范围超出了拟合区间。6. 常见问题与排查技巧实录6.1 高频问题速查表把我在实际使用中遇到的典型问题整理成一张表现象根本原因解决办法中文标签显示为方块字体不含中文字符设置 rcParams 的 font.sans-serif坐标轴负号变方块Unicode 减号与字体不兼容axes.unicode_minus False曲线有明显折角采样点数太少增加 linspace 的点数tan 在渐近线附近画竖线函数值极大直接连线掩膜掉大于阈值的值多组数据叠在一起看不清没有设置垂直偏移每组加独立 offset图例盖住数据默认位置不佳locupper right或手动指定导出图片模糊dpi 太低savefig 时 dpi300图片四周空白太多布局没调整bbox_inchestight振荡曲线密密麻麻看不出趋势坐标系不合适改用 semilogy 或 loglog这张表里的每一条我都实际踩过。特别是前两项几乎每个项目环境都要配一遍。如果你把字体配置写在公共样式文件里整个团队的新人都不用再撞这个墙。高频问题之外有一个会让人困惑的问题是“拟合结果不对”。大部分时候不是代码错而是数据本身分布不符合所选模型比如用线性函数去拟合指数衰减结果残差不仅大还有明显形状。所以出图以后第一件事不是调参数而是看一眼残差分布确认没有系统性偏差。残差如果呈现出“两头翘中间塌”的形态说明模型结构不对换模型比调参数有用得多。6.2 我踩过的几个坑第一个坑包络线图例重复。阻尼衰减那段代码我第一次写的时候给上下两条包络线都加了 label图例里出现两行“包络线”既冗余又难看。后来改成只给其中一条加标签另一条纯视觉辅助图例瞬间清爽。第二个坑XRD 谱图用默认线宽。仪器数据噪声比较多线宽设为默认 1.0 的时候谱线跟噪声混在一起几乎看不出峰。把 lw 提到 1.5并配上深色主色视觉上会立竿见影。这属于那种“看起来不重要、实际影响很大”的细节。第三个坑savefig时忘记处理透明背景。论文插图经常要求白底如果你导出的 PNG 没有控制背景可能是透明背景放在白底文档里看不出来放到深色 PPT 里就露馅了。需要设置facecolorwhite或者提交前统一检查一遍。第四个坑随机种子的复现问题。我给一个项目交付统计图脚本对方跑出来的图跟我演示时完全不一样排查了很久才发现是演示时忘了设置seed。数据模拟类图表必须包含种子、版本号和数据描述这是图表最有价值的三行元信息不仅是为了复现更是为了后期排查时能还原现场。6.3 关于配色和审美的一点建议matplotlib 默认的颜色和字体说实话不太适合直接放进论文。蓝橙相对比、红黑搭配、绿色系列是我日常用得最顺手的组合。上面所有示例里我用了#2E86AB、#D64933、#888888、#9ACDBA这几类颜色它们的共同点是饱和度适中、明度高普通打印和屏幕显示都不容易串色。配色还有一个容易被忽略的原则同色系用于同一性质的曲线异色系用于不同性质的曲线。比如包络线和主曲线用灰蓝对比理论曲线和直方图用红光栅对比读者不用看图例也能明白层次关系。如果你懒得想配色可以从非常基本的取色板里选两三个固定色值做成常量放在公共样式文件里保证所有图表风格统一。我个人实际操作下来的体会是matplotlib 本身并不缺功能缺的是一套“按场景配置参数”的习惯。阻尼曲线、XRD、三角函数、超越函数、随机数与拟合这五项基本覆盖了从物理模拟到实验分析的日常高频需求把每一类的参数逻辑吃透比临摹一百张别人的图更有用。最后分享一个小技巧给自己维护一个plot_style.py把中文字体、默认线宽、配色、DPI、输出格式都封装成一个函数每次新图只要调用它图表风格永远统一——长期下来你会发现这是提升出图效率和质量的投入产出比最高的一件事。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑