mcpField
M
matplotlib-scientific-plotting

matplotlib-scientific-plotting

github.com/jaechang-hits数据与数据库384127 次安装6 天前更新
代码仓库

关于 matplotlib-scientific-plotting

matplotlib-scientific-plotting 是使用 Python Matplotlib 创建科学可视化的技能,面向需要制作图表的研究人员和开发者,涵盖绘图、布局、样式、三维图及导出。

主要功能

  1. 01pyplot 与面向对象绘图接口
  2. 02科学图表类型与多面板布局
  3. 03图形样式和色图自定义
  4. 04三维曲面、散点和线框图
  5. 05导出适合出版的格式

适用场景

  1. 01制作论文用多面板图
  2. 02用统计图比较多个组别
  3. 03以三维方式可视化数据
  4. 04将图表保存为 PDF 或 SVG 以供投稿

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill matplotlib-scientific-plotting

安装后在 Claude Code 中输入/matplotlib-scientific-plotting确认已加载。

详细介绍

matplotlib

概述

Matplotlib 是 Python 的基础可视化库,可用于创建静态、动画和交互式绘图。它同时提供 MATLAB 风格的 pyplot 接口和面向对象的 API,让你能够全面控制图形、坐标轴和绘图元素。它是生成出版级科学图表的必备工具。

适用场景

  • 创建出版级图表,并精确控制每个元素(字体、刻度、颜色、间距)
  • 为论文构建包含复杂子图布局的多面板图
  • 生成标准科学图表类型:折线图、散点图、条形图、直方图、热力图、箱线图、小提琴图、等高线图
  • 将图表导出为矢量格式(PDF、SVG),用于期刊投稿
  • 创建 3D 曲面图、散点图或线框图
  • 自定义色图和配色方案,以提升无障碍性(适合色盲用户)
  • 将图表与 NumPy 数组和 pandas DataFrame 集成
  • 对于快速统计可视化(分布、回归),改用 seaborn
  • 对于带悬停和缩放功能的交互式或基于 Web 的图表,改用 plotly

前置条件

  • Python 包:matplotlib、numpy
  • 可选:pandas(用于绘制 DataFrame)、seaborn(用于预设样式)
  • 运行环境:可用于脚本、Jupyter 笔记本(%matplotlib inline)和 GUI 应用
pip install matplotlib numpy

快速开始

import matplotlib.pyplot as plt
import numpy as np

# Publication-ready figure template: set size, plot, label, save as PDF
fig, ax = plt.subplots(figsize=(6, 4))  # single-column journal width ≈ 6 cm → set here in inches

x = np.linspace(0, 2 * np.pi, 200)
ax.plot(x, np.sin(x), color="steelblue", lw=1.5, label="sin(x)")
ax.plot(x, np.cos(x), color="coral",    lw=1.5, label="cos(x)", linestyle="--")

ax.set_xlabel("x (radians)")
ax.set_ylabel("Amplitude")
ax.set_title("Sine and Cosine Waves")
ax.legend(frameon=False)
ax.spines[["top", "right"]].set_visible(False)  # clean axis style

plt.tight_layout()
plt.savefig("quickstart.pdf", bbox_inches="tight", dpi=300)
print("Saved quickstart.pdf")

核心 API

模块 1:Figure 和 Axes 的创建

基础对象:Figure(画布)和 Axes(绘图区域)。

import matplotlib.pyplot as plt
import numpy as np

# Single plot (recommended: OO interface)
fig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 2 * np.pi, 100)
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)")
ax.set_xlabel("x"); ax.set_ylabel("y")
ax.set_title("Trigonometric Functions")
ax.legend(); ax.grid(True, alpha=0.3)
plt.savefig("basic_plot.png", dpi=300, bbox_inches="tight")
print("Saved basic_plot.png")
# Multi-panel subplots
fig, axes = plt.subplots(2, 2, figsize=(10, 8), constrained_layout=True)
axes[0, 0].plot(x, np.sin(x)); axes[0, 0].set_title("sin(x)")
axes[0, 1].scatter(x[::5], np.cos(x[::5])); axes[0, 1].set_title("cos(x)")
axes[1, 0].bar(["A", "B", "C"], [3, 7, 5]); axes[1, 0].set_title("Bar")
axes[1, 1].hist(np.random.randn(500), bins=30); axes[1, 1].set_title("Histogram")
plt.savefig("subplots.png", dpi=300, bbox_inches="tight")
print("Saved subplots.png with 4 panels")
模块 2:绘图类型

标准科学图表类型。

import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(2, 3, figsize=(15, 9), constrained_layout=True)

# Line plot — trends over time
x = np.linspace(0, 10, 50)
axes[0, 0].plot(x, np.exp(-x/3) * np.sin(x), "b-", linewidth=2)
axes[0, 0].set_title("Line Plot")

# Scatter plot — correlations
np.random.seed(42)
axes[0, 1].scatter(np.random.randn(100), np.random.randn(100), alpha=0.6, c=np.random.rand(100), cmap="viridis")
axes[0, 1].set_title("Scatter Plot")

# Bar chart — categorical comparisons
categories = ["Gene A", "Gene B", "Gene C", "Gene D"]
axes[0, 2].bar(categories, [4.2, 7.1, 3.5, 6.8], color="steelblue", edgecolor="black")
axes[0, 2].set_title("Bar Chart")

# Histogram — distributions
axes[1, 0].hist(np.random.randn(1000), bins=40, edgecolor="black", alpha=0.7)
axes[1, 0].set_title("Histogram")

# Box plot — statistical distributions
data = [np.random.randn(50) + i for i in range(4)]
axes[1, 1].boxplot(data, labels=["Ctrl", "Drug A", "Drug B", "Drug C"])
axes[1, 1].set_title("Box Plot")

# Heatmap — matrix data
matrix = np.random.rand(8, 8)
im = axes[1, 2].imshow(matrix, cmap="coolwarm", aspect="auto")
plt.colorbar(im, ax=axes[1, 2])
axes[1, 2].set_title("Heatmap")

plt.savefig("plot_types.png", dpi=300, bbox_inches="tight")
print("Saved 6 plot types to plot_types.png")
模块 3:样式和自定义

颜色、字体、样式和注释。

import matplotlib.pyplot as plt
import numpy as np

# Use style sheets
plt.style.use("seaborn-v0_8-whitegrid")

# Custom rcParams for publication
plt.rcParams.update({
    "font.size": 12, "axes.labelsize": 14,
    "axes.titlesize": 16, "xtick.labelsize": 10,
    "ytick.labelsize": 10, "legend.fontsize": 11,
})

fig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 5, 100)
ax.plot(x, np.exp(-x), "r--", linewidth=2, label="Exponential decay")
ax.fill_between(x, np.exp(-x) - 0.1, np.exp(-x) + 0.1, alpha=0.2, color="red")

# Annotations
ax.annotate("Half-life", xy=(0.693, 0.5), xytext=(2, 0.7),
            arrowprops=dict(arrowstyle="->", color="black"),
            fontsize=12, fontweight="bold")
ax.set_xlabel("Time (s)"); ax.set_ylabel("Signal")
ax.legend()
plt.savefig("styled_plot.png", dpi=300, bbox_inches="tight")
print("Saved styled_plot.png")
模块 4:高级布局

马赛克布局、GridSpec、内嵌图。

import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import numpy as np

# Mosaic layout — named axes
fig, axes = plt.subplot_mosaic(
    [["main", "right"], ["main", "bottom_right"]],
    figsize=(10, 7), constrained_layout=True,
    gridspec_kw={"width_ratios": [2, 1]}
)
x = np.linspace(0, 10, 200)
axes["main"].plot(x, np.sin(x) * np.exp(-x/5), "b-", linewidth=2)
axes["main"].set_title("Main Panel")
axes["right"].hist(np.random.randn(300), bins=20, orientation="horizontal")
axes["right"].set_title("Distribution")
axes["bottom_right"].bar(["A", "B"], [3, 5])
axes["bottom_right"].set_title("Summary")
plt.savefig("mosaic_layout.png", dpi=300, bbox_inches="tight")
print("Saved mosaic_layout.png")
模块 5:3D 可视化

曲面图、散点图和线框图。

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection="3d")

# Surface plot
u = np.linspace(0, 2 * np.pi, 50)
v = np.linspace(0, np.pi, 50)
X = np.outer(np.cos(u), np.sin(v))
Y = np.outer(np.sin(u), np.sin(v))
Z = np.outer(np.ones_like(u), np.cos(v))

ax.plot_surface(X, Y, Z, cmap="viridis", alpha=0.8)
ax.set_xlabel("X"); ax.set_ylabel("Y"); ax.set_zlabel("Z")
ax.set_title("3D Surface Plot")
plt.savefig("surface_3d.png", dpi=300, bbox_inches="tight")
print("Saved surface_3d.png")
模块 6:导出和保存

使用出版级设置输出为各种格式。

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=(6, 4))
ax.plot([1, 2, 3], [1, 4, 9], "ko-")
ax.set_title("Export Example")

# High-res PNG for presentations
fig.savefig("figure.png", dpi=300, bbox_inches="tight", facecolor="white")

# Vector PDF for journal submission
fig.savefig("figure.pdf", bbox_inches="tight")

# SVG for web
fig.savefig("figure.svg", bbox_inches="tight")

# Transparent background
fig.savefig("figure_transparent.png", dpi=300, bbox_inches="tight", transparent=True)

plt.close(fig)  # Free memory
print("Exported to PNG, PDF, SVG, and transparent PNG")

常见工作流

工作流 1:用于出版的多面板图

目标:为论文创建一张组合不同图表类型的 4 面板图。

import matplotlib.pyplot as plt
import numpy as np

np.random.seed(42)
fig, axes = plt.subplots(2, 2, figsize=(10, 8), constrained_layout=True)

# Panel A: Time series
t = np.linspace(0, 24, 100)
axes[0, 0].plot(t, 50 + 10 * np.sin(t * np.pi / 12), "b-", linewidth=2)
axes[0, 0].set_xlabel("Time (h)"); axes[0, 0].set_ylabel("Expression")
axes[0, 0].set_title("A", loc="left", fontweight="bold")

# Panel B: Volcano plot
fc = np.random.randn(500)
pval = -np.log10(np.random.uniform(0.0001, 1, 500))
colors = ["red" if abs(f) > 1 and p > 2 else "grey" for f, p in zip(fc, pval)]
axes[0, 1].scatter(fc, pval, c=colors, s=10, alpha=0.7)
axes[0, 1].axhline(2, ls="--", color="black", alpha=0.5)
axes[0, 1].set_xlabel("log₂ FC"); axes[0, 1].set_ylabel("-log₁₀ p-value")
axes[0, 1].set_title("B", loc="left", fontweight="bold")

# Panel C: Bar chart with error bars
means = [3.2, 5.1, 4.7, 6.3]
sems = [0.4, 0.6, 0.3, 0.5]
axes[1, 0].bar(["Ctrl", "Drug A", "Drug B", "Combo"], means, yerr=sems,
               capsize=5, color="steelblue", edgecolor="black")
axes[1, 0].set_ylabel("Response"); axes[1, 0].set_title("C", loc="left", fontweight="bold")

# Panel D: Heatmap
data = np.random.randn(6, 4)
im = axes[1, 1].imshow(data, cmap="RdBu_r", aspect="auto")
plt.colorbar(im, ax=axes[1, 1])
axes[1, 1].set_title("D", loc="left", fontweight="bold")

fig.savefig("publication_figure.pdf", bbox_inches="tight")
print("Saved publication_figure.pdf (4 panels)")
工作流 2:统计比较图

目标:绘制带有单个数据点和显著性注释的条形图。

import matplotlib.pyplot as plt
import numpy as np

np.random.seed(42)
groups = {"Control": np.random.normal(5, 1.2, 20),
          "Treatment A": np.random.normal(7, 1.5, 20),
          "Treatment B": np.random.normal(6, 1.0, 20)}

fig, ax = plt.subplots(figsize=(6, 5))
positions = range(len(groups))
for i, (name, data) in enumerate(groups.items()):
    ax.bar(i, np.mean(data), yerr=np.std(data)/np.sqrt(len(data)),
           capsize=5, color=["#4C72B0", "#DD8452", "#55A868"][i],
           edgecolor="black", alpha=0.8, width=0.6)
    # Overlay individual data points
    ax.scatter(np.full_like(data, i) + np.random.uniform(-0.15, 0.15, len(data)),
               data, color="black", s=15, alpha=0.5, zorder=5)

ax.set_xticks(positions); ax.set_xticklabels(groups.keys())
ax.set_ylabel("Measurement")

# Add significance bracket
y_max = max(max(d) for d in groups.values()) + 1
ax.plot([0, 0, 1, 1], [y_max, y_max + 0.2, y_max + 0.2, y_max], "k-", linewidth=1)
ax.text(0.5, y_max + 0.3, "**", ha="center", fontsize=14)

fig.savefig("comparison_plot.png", dpi=300, bbox_inches="tight")
print("Saved comparison_plot.png")

关键参数

参数模块默认值范围 / 选项效果
figsize图形创建(6.4, 4.8)(w, h),单位为英寸图形尺寸
dpisavefig10072-600分辨率:印刷用 300,网页用 150
bbox_inchessavefigNone"tight"、None裁剪图形周围的空白
constrained_layoutsubplotsFalseTrue/False自动调整间距以避免重叠
cmap热力图/散点图"viridis""viridis"、"coolwarm"、"RdBu_r" 等用于数据映射的色图
alpha所有绘图类型1.00.0-1.0透明度(0=不可见,1=不透明)
linewidth折线图1.50.5-5.0线条粗细,单位为点
s散点图201-500标记大小,单位为点²
bins直方图105-100 或数组直方图的分箱数量
projectionadd_subplotNone"3d"、"polar"坐标轴投影类型

最佳实践

  1. 始终在生产代码中使用 OO 接口(fig, ax = plt.subplots())。仅在快速交互式探索时使用 plt.plot()

  2. 使用 constrained_layout=True,防止标签和标题重叠:

    fig, ax = plt.subplots(figsize=(8, 5), constrained_layout=True)
    
  3. 选择无障碍色图:使用 viridis、cividis 或 plasma(感知均匀且适合色盲用户)。避免使用 jet 和 rainbow

  4. 保存后关闭图形,以避免循环中发生内存泄漏:

    plt.close(fig)  # After savefig
    
  5. 设置合适的 DPI:印刷/期刊用 300,网页/幻灯片用 150,仅屏幕显示用 72

  6. 对大型数据集使用 rasterized=True,以减小 PDF/SVG 文件大小:

    ax.scatter(x, y, rasterized=True)  # Vector labels + rasterized data
    
  7. 统一标注面板:对于多面板图,在每个子图的左上角使用粗体字母(A、B、C、D)

常用配方

配方:自定义调色板

适用场景:在论文的多张图中保持颜色一致。

import matplotlib.pyplot as plt

# Define a custom palette
palette = {"control": "#4C72B0", "treatment": "#DD8452", "combo": "#55A868"}

fig, ax = plt.subplots()
for group, color in palette.items():
    ax.bar(group, [5, 7, 6][list(palette.keys()).index(group)], color=color)
plt.savefig("custom_palette.png", dpi=300, bbox_inches="tight")
配方:双 Y 轴

适用场景:在同一张图中绘制刻度不同的两个变量。

import matplotlib.pyplot as plt
import numpy as np

fig, ax1 = plt.subplots(figsize=(8, 5))
x = np.arange(10)
ax1.bar(x, np.random.randint(10, 100, 10), alpha=0.7, color="steelblue", label="Count")
ax1.set_ylabel("Count", color="steelblue")

ax2 = ax1.twinx()
ax2.plot(x, np.cumsum(np.random.rand(10)), "r-o", linewidth=2, label="Cumulative")
ax2.set_ylabel("Cumulative", color="red")

fig.legend(loc="upper left", bbox_to_anchor=(0.15, 0.95))
plt.savefig("twin_axes.png", dpi=300, bbox_inches="tight")
配方:局部放大图

适用场景:展示较大图表中的放大区域。

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 10, 500)
y = np.sin(x) * np.exp(-x / 5)
ax.plot(x, y, "b-", linewidth=2)

# Inset
axins = ax.inset_axes([0.5, 0.5, 0.4, 0.4])
axins.plot(x, y, "b-", linewidth=2)
axins.set_xlim(1, 3); axins.set_ylim(0.2, 0.8)
ax.indicate_inset_zoom(axins, edgecolor="black")
plt.savefig("inset_zoom.png", dpi=300, bbox_inches="tight")

故障排除

问题原因解决方案
标签或标题重叠未管理布局在 plt.subplots() 中添加 constrained_layout=True
UserWarning: tight_layout与 constrained_layout 不兼容只使用其中一种:constrained_layout 或 tight_layout(),不要同时使用
Jupyter 中的图像模糊默认 DPI 较低设置 %config InlineBackend.figure_format = 'retina'
循环中内存不断增长图表未关闭每次 savefig() 后添加 plt.close(fig)
字体未找到警告系统缺少该字体使用 plt.rcParams["font.sans-serif"] = ["DejaVu Sans"]
PDF/SVG 文件体积过大矢量图中数据点过多对占用较大的绘图元素使用 rasterized=True
3D 图无法旋转交互式后端问题在 Jupyter 中使用 %matplotlib widget,或在脚本中使用 plt.show()
颜色栏尺寸不合适默认尺寸与坐标轴不匹配使用 fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)

参考资料

评论

支持 Markdown