AI 辅助数据分析与可视化🔗
关键词: 数据分析, 可视化, Python, pandas, matplotlib, seaborn, 统计分析, 科研绘图
难度: ⭐⭐
预计阅读时间: 35 分钟
最后更新: 2026-04-09
本章导读🔗
数据分析和可视化是科研工作中最耗时的环节之一。从实验数据清洗、统计分析到制作符合期刊要求的图表,每一步都涉及大量的编程和调参工作。AI 工具可以极大地加速这一过程——你只需用自然语言描述"我有什么数据、想做什么分析、想画什么图",AI 就能生成可直接运行的 Python 代码。
本章将系统介绍如何用 AI 辅助完成科研数据分析的全流程:
- 数据清洗:用 AI 生成 pandas 代码处理原始数据
- 统计分析:让 AI 帮你选择合适的统计方法并解释结果
- 科研绑定:生成 matplotlib/seaborn 代码,制作达到期刊发表标准的图表
- 实操演示:从原始数据到发表级图表的完整流程
前提假设: 你有基本的 Python 使用经验(能运行脚本、了解 pandas/numpy 基础),但不需要精通数据分析或绑定。如果你还不熟悉 Python 环境配置,请先阅读 VSCode Vibe Coding 教程。
1. AI 辅助数据清洗🔗
数据清洗(Data Cleaning)是数据分析的第一步,也是最枯燥但最重要的一步。原始实验数据往往包含缺失值、异常值、格式不一致等问题。传统做法是手动写大量 pandas 代码来处理——现在你可以让 AI 来生成这些代码。
1.1 用 AI 生成 pandas 处理代码🔗
核心思路: 把你的数据结构和处理需求描述清楚,让 AI 一次性生成完整的清洗流程。
通用数据清洗 Prompt 模板:
我有一个实验数据文件 [文件名],格式为 [CSV/Excel/TSV]。
数据包含以下列:
- [列名1]:[数据类型和含义]
- [列名2]:[数据类型和含义]
- ...
数据存在以下问题:
1. [具体问题,如"第3列有空值"]
2. [具体问题,如"时间格式不统一"]
3. [具体问题,如"可能有异常值"]
请用 Python (pandas) 帮我完成数据清洗:
1. 读入数据
2. 检查数据基本信息(shape、dtypes、缺失值统计)
3. 处理上述问题
4. 输出清洗后的数据并保存
请加上必要的注释,并在每一步后打印处理结果以便我检查。
实例——处理蛋白质活性测定数据:
我有一个酶活性测定的实验数据 enzyme_activity.csv,包含以下列:
- sample_id:样本编号(字符串)
- concentration:底物浓度(μM,浮点数)
- absorbance_450:450nm 吸光度(浮点数)
- temperature:反应温度(℃,应为 25 或 37)
- replicate:重复编号(1, 2, 3)
- date:实验日期(格式不统一,有 "2025-03-01" 和 "03/01/2025" 混用)
数据有约 500 行。已知问题:
1. 约 5% 的 absorbance_450 是空值
2. date 列格式不统一
3. 有几个 absorbance_450 为负值(仪器错误)
4. concentration 列有个别 "#N/A" 文本
请用 pandas 完成数据清洗,并生成一份清洗报告(清洗前后对比)。
AI 生成的代码通常类似:
import pandas as pd
import numpy as np
# ============ 1. 读入数据 ============
df = pd.read_csv('enzyme_activity.csv', na_values=['#N/A', 'N/A', ''])
print("=== 原始数据概况 ===")
print(f"数据量: {df.shape[0]} 行, {df.shape[1]} 列")
print(f"\n数据类型:\n{df.dtypes}")
print(f"\n缺失值统计:\n{df.isnull().sum()}")
print(f"\n数值列描述性统计:\n{df.describe()}")
# ============ 2. 统一日期格式 ============
df['date'] = pd.to_datetime(df['date'], format='mixed')
print(f"\n日期范围: {df['date'].min()} ~ {df['date'].max()}")
# ============ 3. 处理负值(仪器错误) ============
n_negative = (df['absorbance_450'] < 0).sum()
print(f"\n吸光度负值数量: {n_negative}")
df.loc[df['absorbance_450'] < 0, 'absorbance_450'] = np.nan
# ============ 4. 处理缺失值 ============
n_missing_before = df['absorbance_450'].isnull().sum()
# 对每个 (sample_id, concentration) 组,用同组均值填充
df['absorbance_450'] = df.groupby(['sample_id', 'concentration'])[
'absorbance_450'
].transform(lambda x: x.fillna(x.mean()))
n_missing_after = df['absorbance_450'].isnull().sum()
print(f"\n缺失值处理: {n_missing_before} → {n_missing_after}")
# 仍然为空的行(整组都缺失),直接删除
df = df.dropna(subset=['absorbance_450'])
# ============ 5. 验证 temperature 值 ============
invalid_temp = df[~df['temperature'].isin([25, 37])]
if len(invalid_temp) > 0:
print(f"\n异常温度值: {invalid_temp['temperature'].unique()}")
df = df[df['temperature'].isin([25, 37])]
# ============ 6. 保存清洗后数据 ============
df.to_csv('enzyme_activity_cleaned.csv', index=False)
print(f"\n=== 清洗完成 ===")
print(f"最终数据量: {df.shape[0]} 行")
关键技巧: 在 Prompt 中尽可能详细地描述数据结构和已知问题。AI 无法看到你的实际数据文件,所以信息越完整,生成的代码就越准确。
1.2 缺失值处理策略🔗
处理缺失值是数据清洗中最常见的任务。不同场景适合不同的策略:
| 策略 | 适用场景 | pandas 代码 | 注意事项 |
|---|---|---|---|
| 直接删除 | 缺失比例 <5%,数据量充足 | df.dropna() | 最简单但会丢失数据 |
| 均值/中位数填充 | 数值型、近似正态分布 | df.fillna(df.mean()) | 会降低数据方差 |
| 前向/后向填充 | 时间序列数据 | df.fillna(method='ffill') | 适合连续测量 |
| 分组填充 | 有分组结构的数据 | df.groupby('group')['col'].transform(...) | 保留组内差异 |
| 插值 | 平滑变化的数值 | df.interpolate() | 适合趋势性数据 |
| 标记为特殊值 | 缺失本身有含义 | df.fillna(-999) | 仅在特定模型中适用 |
让 AI 帮你选择策略的 Prompt:
我的数据集有以下缺失值情况:
- 总共 1000 行数据
- column_A:缺失 3%(数值型,正态分布)
- column_B:缺失 15%(类别型,3 个类别)
- column_C:缺失 30%(数值型,是某些样本没有测量)
- column_D:缺失 1%(数值型,时间序列)
请为每一列推荐最合适的缺失值处理策略,
解释理由,并给出 pandas 代码。
1.3 异常值检测🔗
异常值(Outlier)在实验数据中非常常见,可能是仪器故障、操作失误或真实的极端值。AI 可以帮你快速实现多种检测方法。
异常值检测 Prompt:
请用 Python 对我的数据进行异常值检测,使用以下三种方法:
1. Z-score 方法(阈值 ±3)
2. IQR 方法(1.5倍四分位距)
3. 可视化方法(箱线图 + 直方图)
数据列为 df['absorbance_450'],大约 500 个数值。
请对比三种方法检测到的异常值,并给出处理建议。
AI 通常会生成包含可视化的完整检测代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def detect_outliers(series, name="data"):
"""用三种方法检测异常值"""
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
# --- 方法 1: Z-score ---
z_scores = np.abs((series - series.mean()) / series.std())
outliers_z = z_scores > 3
# --- 方法 2: IQR ---
Q1, Q3 = series.quantile(0.25), series.quantile(0.75)
IQR = Q3 - Q1
lower, upper = Q1 - 1.5 * IQR, Q3 + 1.5 * IQR
outliers_iqr = (series < lower) | (series > upper)
# --- 可视化 ---
axes[0].boxplot(series.dropna())
axes[0].set_title(f'{name} - Boxplot')
axes[1].hist(series.dropna(), bins=30, edgecolor='black')
axes[1].axvline(lower, color='r', linestyle='--', label=f'IQR bounds')
axes[1].axvline(upper, color='r', linestyle='--')
axes[1].set_title(f'{name} - Histogram + IQR')
axes[1].legend()
axes[2].scatter(range(len(series)), series, c=outliers_z,
cmap='coolwarm', alpha=0.5, s=10)
axes[2].set_title(f'{name} - Z-score Outliers')
plt.tight_layout()
plt.savefig(f'outlier_detection_{name}.png', dpi=150, bbox_inches='tight')
plt.show()
print(f"Z-score 方法检测到 {outliers_z.sum()} 个异常值")
print(f"IQR 方法检测到 {outliers_iqr.sum()} 个异常值")
return outliers_z, outliers_iqr
# 使用
outliers_z, outliers_iqr = detect_outliers(df['absorbance_450'], 'Absorbance')
注意: 异常值不一定要删除!在科研中,异常值可能代表了有意义的生物学现象。AI 可以帮你检测异常值,但是否删除需要你根据科学判断来决定。
1.4 数据类型转换与格式统一🔗
实验数据最常见的格式问题:
请帮我处理以下数据格式问题,用 pandas 代码实现:
1. 时间列:有 "2025-03-01", "03/01/2025", "March 1, 2025" 三种格式
→ 统一为 "YYYY-MM-DD" 格式
2. 浓度列:有 "10 μM", "10μM", "10uM", "0.01 mM" 混用
→ 统一为 μM 数值
3. 基因名:有 "TP53", "tp53", "Tp53" 大小写混乱
→ 统一为全大写
4. 数值列中混入了文本:"<LOD"(低于检测限), "N/A"
→ "<LOD" 替换为检测限的一半值(LOD=0.1),"N/A" 设为空值
2. AI 辅助统计分析🔗
统计分析是论文方法和结果部分的核心。选错统计方法是 reviewer 退稿的常见原因之一。AI 可以帮你根据数据特征选择合适的方法,生成分析代码,并解释结果——但你必须理解统计方法的基本逻辑,不能完全依赖 AI。
2.1 选择合适的统计方法🔗
统计方法选择是初学者最容易犯错的地方。 以下是常见科研场景的统计方法速查表:
| 研究目的 | 数据条件 | 推荐方法 | Python 库 |
|---|---|---|---|
| 比较两组均值 | 正态分布、方差齐性 | 独立样本 t 检验 (Independent t-test) | scipy.stats.ttest_ind |
| 比较两组均值 | 非正态分布 | Mann-Whitney U 检验 | scipy.stats.mannwhitneyu |
| 比较配对数据 | 正态分布 | 配对 t 检验 (Paired t-test) | scipy.stats.ttest_rel |
| 比较配对数据 | 非正态分布 | Wilcoxon 符号秩检验 | scipy.stats.wilcoxon |
| 比较三组及以上均值 | 正态、方差齐性 | 单因素方差分析 (One-way ANOVA) | scipy.stats.f_oneway |
| 比较三组及以上均值 | 非正态分布 | Kruskal-Wallis 检验 | scipy.stats.kruskal |
| ANOVA 显著后两两比较 | — | Tukey HSD 事后检验 | statsmodels.stats.multicomp |
| 两个连续变量是否相关 | 线性关系、正态 | Pearson 相关 | scipy.stats.pearsonr |
| 两个连续变量是否相关 | 非线性或非正态 | Spearman 秩相关 | scipy.stats.spearmanr |
| 两个分类变量是否独立 | 频率数据 | 卡方检验 (Chi-square) | scipy.stats.chi2_contingency |
| 预测连续因变量 | 线性关系 | 线性回归 (Linear Regression) | sklearn.linear_model / statsmodels |
| 预测二分类因变量 | — | 逻辑回归 (Logistic Regression) | sklearn.linear_model |
| 生存分析 | 时间-事件数据 | Kaplan-Meier / Cox 回归 | lifelines |
| 多组间多变量差异 | 多个因变量 | MANOVA / PCA + 聚类 | statsmodels / sklearn |
让 AI 帮你选择统计方法的 Prompt:
请帮我选择合适的统计分析方法。我的实验设计如下:
实验目的:比较 [具体目的]
实验分组:[列出各组,如"野生型 vs 突变体 vs 突变体+药物处理"]
样本量:每组 [n] 个
测量指标:[具体指标,如"蛋白表达量(连续变量)"]
数据特点:[如"初步观察基本符合正态分布"或"有明显偏态"]
请:
1. 推荐最合适的统计方法及理由
2. 告诉我需要先做哪些前提检验(正态性、方差齐性等)
3. 给出完整的 Python 代码(包含前提检验和主分析)
4. 说明如何正确报告结果(按 APA 格式)
2.2 AI 辅助统计代码生成🔗
完整统计分析流程示例 Prompt:
我有一个蛋白质表达量的实验数据,三组(Control, Treatment_A, Treatment_B),
每组 10 个生物学重复。数据存在 df 中,列为 'group' 和 'expression'。
请用 Python 完成以下分析:
1. 描述性统计(均值、标准差、标准误)
2. 正态性检验(Shapiro-Wilk)
3. 方差齐性检验(Levene's test)
4. 根据检验结果选择合适的方法进行组间比较
5. 如果总体比较显著,做事后多重比较
6. 生成一个包含显著性标注的柱状图
7. 打印规范的统计结果报告
AI 生成的代码通常如下:
import pandas as pd
import numpy as np
from scipy import stats
from statsmodels.stats.multicomp import pairwise_tukeyhsd
import matplotlib.pyplot as plt
import seaborn as sns
# ============ 1. 描述性统计 ============
desc = df.groupby('group')['expression'].agg(['mean', 'std', 'sem', 'count'])
print("=== 描述性统计 ===")
print(desc.round(3))
print()
# ============ 2. 正态性检验 ============
print("=== Shapiro-Wilk 正态性检验 ===")
groups = df['group'].unique()
normal_flag = True
for g in groups:
data = df[df['group'] == g]['expression']
stat, p = stats.shapiro(data)
result = "正态" if p > 0.05 else "非正态"
print(f" {g}: W={stat:.4f}, p={p:.4f} → {result}")
if p <= 0.05:
normal_flag = False
print()
# ============ 3. 方差齐性检验 ============
group_data = [df[df['group'] == g]['expression'].values for g in groups]
stat, p = stats.levene(*group_data)
equal_var = p > 0.05
print(f"=== Levene 方差齐性检验 ===")
print(f" F={stat:.4f}, p={p:.4f} → {'方差齐性' if equal_var else '方差不齐'}")
print()
# ============ 4. 组间比较 ============
if normal_flag and equal_var:
# 满足参数检验条件 → One-way ANOVA
stat, p = stats.f_oneway(*group_data)
print(f"=== One-way ANOVA ===")
print(f" F={stat:.4f}, p={p:.4f}")
test_name = "ANOVA"
else:
# 不满足 → Kruskal-Wallis
stat, p = stats.kruskal(*group_data)
print(f"=== Kruskal-Wallis 检验 ===")
print(f" H={stat:.4f}, p={p:.4f}")
test_name = "Kruskal-Wallis"
# ============ 5. 事后多重比较 ============
if p < 0.05:
print(f"\n=== Tukey HSD 事后比较 ===")
tukey = pairwise_tukeyhsd(df['expression'], df['group'], alpha=0.05)
print(tukey)
2.3 让 AI 解释统计结果🔗
拿到统计结果后,可以让 AI 帮你用论文语言描述:
以下是我的统计分析结果:
- 三组数据:Control (mean=1.00, SD=0.15, n=10), Treatment_A (mean=1.45, SD=0.20, n=10),
Treatment_B (mean=1.82, SD=0.25, n=10)
- Shapiro-Wilk 检验: 三组均 p>0.05(正态)
- Levene 检验: p=0.23(方差齐性)
- One-way ANOVA: F(2,27)=47.3, p<0.001
- Tukey HSD: Control vs Treatment_A (p=0.001), Control vs Treatment_B (p<0.001),
Treatment_A vs Treatment_B (p=0.003)
请用以下格式帮我撰写 Results 部分的统计描述:
1. 英文版本(适合提交论文)
2. 中文版本(适合组会报告)
遵循 APA 统计报告规范。
2.4 常见统计陷阱🔗
以下是 reviewer 最常指出的统计问题,也是 AI 可能忽略的地方:
| 常见错误 | 正确做法 | 说明 |
|---|---|---|
| 不检验正态性就用 t 检验 | 先做 Shapiro-Wilk 检验 | 小样本尤其关键 |
| 多次 t 检验代替 ANOVA | 三组以上先做 ANOVA,再做事后检验 | 否则 I 类错误膨胀 |
| p 值报告为 "p=0.000" | 写 "p<0.001" | p 值不会等于 0 |
| 只报告 p 值不报告效应量 | 同时报告效应量(Cohen's d, η²) | 越来越多期刊要求 |
| 两组数据不独立却用独立 t 检验 | 配对设计用配对 t 检验 | 前后对比、左右对比 |
| 混淆生物学重复和技术重复 | n = 生物学重复数 | 这是最常见的审稿意见 |
| 非正态数据用均值±SD | 用中位数±IQR 或展示完整分布 | boxplot 比 barplot 信息量大 |
| 不做多重比较校正 | Bonferroni / Benjamini-Hochberg 校正 | 多次检验时必须校正 |
让 AI 帮你检查统计分析的 Prompt:
以下是我论文中 Results 部分的统计分析描述。
请以一个严格的统计学审稿人的角度检查:
1. 统计方法选择是否正确?
2. 前提假设检验是否充分?
3. 结果报告格式是否规范?
4. 是否存在常见的统计错误?
5. 还需要补充哪些分析?
我的实验设计:[简述]
统计描述:[粘贴你的 Results 段落]
2.5 效应量计算🔗
越来越多的期刊要求在报告 p 值的同时报告效应量(Effect Size)。一些常用的效应量指标:
请帮我计算以下统计分析的效应量,用 Python 实现:
1. 两组 t 检验 → Cohen's d
2. One-way ANOVA → η²(eta-squared)和 ω²(omega-squared)
3. 相关分析 → r 本身就是效应量,但请给出 r² 和 95% CI
4. 卡方检验 → Cramér's V
数据在 df 中,分组列为 'group',数值列为 'value'。
同时请告诉我如何解释这些效应量的大小
(小效应/中效应/大效应的阈值)。
常见效应量解读标准:
| 效应量 | 小效应 | 中效应 | 大效应 |
|---|---|---|---|
| Cohen's d | 0.2 | 0.5 | 0.8 |
| η² | 0.01 | 0.06 | 0.14 |
| r | 0.1 | 0.3 | 0.5 |
| Cramér's V | 0.1 | 0.3 | 0.5 |
3. AI 辅助科研绑定🔗
科研绘图是 AI 辅助编程中投入产出比最高的场景。传统手动调参一张图可能需要几个小时,而用 AI 只需几分钟就能生成接近发表质量的代码——剩下的只需要微调细节。
3.1 期刊图片格式要求🔗
在让 AI 生成绑定代码之前,必须先了解目标期刊的图片要求。以下是主要期刊的通用规范:
主要期刊图片规格一览🔗
| 要求 | Nature | Science | Cell | 一般期刊 |
|---|---|---|---|---|
| 文件格式 | TIFF/EPS/PDF | EPS/PDF | TIFF/EPS/PDF | TIFF/PDF/PNG |
| 分辨率(DPI) | 300(照片)/600(线图) | 300+ | 300+ | 300+ |
| 颜色模式 | RGB(线上)/ CMYK(印刷) | RGB | RGB/CMYK | RGB |
| 单栏宽度 | 89 mm (3.5 in) | 85 mm (3.35 in) | 85 mm (3.35 in) | 80-90 mm |
| 双栏宽度 | 183 mm (7.2 in) | 174 mm (6.85 in) | 174 mm (6.85 in) | 170-180 mm |
| 最大高度 | 247 mm (9.7 in) | 230 mm (9.1 in) | 247 mm (9.7 in) | ~240 mm |
| 字体 | Helvetica/Arial | Helvetica/Arial | Arial/Helvetica | Arial/Helvetica |
| 最小字号 | 5 pt | 6 pt | 6 pt | 6 pt |
| 推荐字号 | 7-8 pt | 7-9 pt | 7-8 pt | 7-10 pt |
| 线宽 | 0.5-1.5 pt | 0.5-1.0 pt | 0.5-1.0 pt | 0.5-1.5 pt |
配色方案推荐🔗
基本原则: 科研图表的配色要同时满足美观、可区分和色盲友好三个标准。
| 配色方案 | 适用场景 | 来源 | Python 代码 |
|---|---|---|---|
| Paul Tol's Bright | 离散分类(≤7 色) | colorbrewer | ['#4477AA','#EE6677','#228833','#CCBB44','#66CCEE','#AA3377','#BBBBBB'] |
| ColorBrewer Set2 | 离散分类(≤8 色) | seaborn 内置 | sns.color_palette('Set2') |
| Viridis | 连续色阶 | matplotlib 默认 | plt.cm.viridis |
| RdBu | 双向发散(如热图) | matplotlib | plt.cm.RdBu_r |
| Nature 常用 | 仿 Nature 风格 | 自定义 | ['#E64B35','#4DBBD5','#00A087','#3C5488','#F39B7F','#8491B4'] |
| Science 常用 | 仿 Science 风格 | 自定义 | ['#3B4992','#EE0000','#008B45','#631879','#008280','#BB0021'] |
色盲友好提示: 避免同时使用 红+绿 的组合。约 8% 的男性有红绿色盲。建议使用 蓝+橙、蓝+红 的搭配,或使用 Viridis/Cividis 色阶。可以用 Color Oracle 软件模拟色盲视觉效果。
3.2 发表级绑定的基础设置🔗
以下是一套"万能"的 matplotlib 全局设置,适用于大多数期刊:
import matplotlib.pyplot as plt
import matplotlib as mpl
# ============ 期刊级图表全局设置 ============
def set_publication_style():
"""设置适合期刊发表的 matplotlib 全局参数"""
mpl.rcParams.update({
# --- 字体 ---
'font.family': 'Arial', # 大多数期刊要求 Arial 或 Helvetica
'font.size': 8, # 基础字号 8pt
'axes.titlesize': 9, # 子图标题
'axes.labelsize': 8, # 坐标轴标签
'xtick.labelsize': 7, # 刻度标签
'ytick.labelsize': 7,
'legend.fontsize': 7, # 图例
# --- 线条 ---
'axes.linewidth': 0.8, # 坐标轴线宽
'xtick.major.width': 0.8, # 刻度线宽
'ytick.major.width': 0.8,
'xtick.major.size': 3, # 刻度线长
'ytick.major.size': 3,
'lines.linewidth': 1.0, # 数据线宽
'lines.markersize': 4, # 标记大小
# --- 图像 ---
'figure.dpi': 150, # 屏幕显示 DPI
'savefig.dpi': 300, # 保存 DPI(照片用 300,线图用 600)
'savefig.bbox': 'tight', # 自动裁剪白边
'savefig.pad_inches': 0.05, # 留极小的边距
# --- 其他 ---
'axes.spines.top': False, # 隐藏上边框
'axes.spines.right': False, # 隐藏右边框(更简洁)
'legend.frameon': False, # 图例无边框
'pdf.fonttype': 42, # PDF 中嵌入字体(期刊要求)
'ps.fonttype': 42,
})
# 在脚本开头调用
set_publication_style()
# Nature 单栏宽度
FIG_WIDTH_SINGLE = 89 / 25.4 # 89mm → inches
# Nature 双栏宽度
FIG_WIDTH_DOUBLE = 183 / 25.4 # 183mm → inches
重要:
pdf.fonttype: 42这个设置非常关键!它确保 PDF 中的字体是 TrueType 而非 Type 3,否则很多期刊的投稿系统会报错。
3.3 常见科研图表类型及 Prompt 模板🔗
柱状图 + 显著性标注(最常用)🔗
请用 Python (matplotlib) 画一张适合 Nature 投稿的柱状图:
数据:三组(Control, Treatment_A, Treatment_B),
每组 mean 和 SEM 已计算好。
显著性:Control vs Treatment_A (p<0.05),
Control vs Treatment_B (p<0.001)
要求:
- 单栏宽度(89mm),高度约 60mm
- 每个 bar 上添加散点(jitter)展示原始数据
- 显著性标注用横线 + 星号(* p<0.05, ** p<0.01, *** p<0.001)
- 配色方案:Nature 风格(灰、蓝、红)
- Y 轴标签:Relative Expression
- 无上边框和右边框
- 字体 Arial,8pt
- 保存为 PDF 和 600 DPI 的 TIFF
以下是 AI 通常生成的参考代码(经过微调):
import matplotlib.pyplot as plt
import numpy as np
set_publication_style() # 使用上面定义的全局设置
# --- 数据 ---
groups = ['Control', 'Treatment A', 'Treatment B']
means = [1.0, 1.45, 1.82]
sems = [0.05, 0.06, 0.08]
# 原始数据点(用于散点叠加)
raw_data = [
np.random.normal(1.0, 0.15, 10),
np.random.normal(1.45, 0.20, 10),
np.random.normal(1.82, 0.25, 10)
]
# --- Nature 配色 ---
colors = ['#BFBFBF', '#4DBBD5', '#E64B35']
# --- 绑定 ---
fig, ax = plt.subplots(figsize=(89/25.4, 60/25.4)) # 单栏宽,适中高度
# 柱状图
bars = ax.bar(range(3), means, yerr=sems, capsize=3,
color=colors, edgecolor='black', linewidth=0.5,
width=0.6, error_kw={'linewidth': 0.8})
# 散点叠加
for i, data in enumerate(raw_data):
jitter = np.random.uniform(-0.15, 0.15, len(data))
ax.scatter(i + jitter, data, color='black', s=8, alpha=0.6,
zorder=5, linewidths=0)
# 显著性标注
def add_significance(ax, x1, x2, y, p_text, h=0.03):
"""添加显著性标注横线和星号"""
ax.plot([x1, x1, x2, x2], [y, y+h, y+h, y], lw=0.8, c='black')
ax.text((x1+x2)/2, y+h, p_text, ha='center', va='bottom', fontsize=7)
add_significance(ax, 0, 1, 1.7, '*')
add_significance(ax, 0, 2, 1.9, '***')
# --- 格式调整 ---
ax.set_xticks(range(3))
ax.set_xticklabels(groups)
ax.set_ylabel('Relative Expression')
ax.set_ylim(0, 2.2)
# 保存
fig.savefig('barplot.pdf')
fig.savefig('barplot.tiff', dpi=600)
plt.show()
折线图(时间序列 / 剂量-反应)🔗
请画一张展示酶活性随底物浓度变化的 Michaelis-Menten 曲线:
数据:6 个浓度点,每个 3 次重复
X 轴:Substrate Concentration (μM)
Y 轴:Reaction Rate (μM/min)
拟合方程:v = Vmax * [S] / (Km + [S])
要求:
- 散点展示原始数据(带误差棒,SEM)
- 叠加拟合曲线(虚线或实线均可)
- 标注 Vmax 和 Km 值
- 图片大小:Nature 单栏宽度
- 保存为 PDF
热图(Heatmap)🔗
请用 seaborn 画一张基因表达热图:
数据:pandas DataFrame,行是基因名(20 个),列是样本(6 个)
数值是 log2(fold change),范围约 [-3, 3]
要求:
- 使用 RdBu_r 配色(红=上调,蓝=下调)
- 行列都做层次聚类(hierarchical clustering)
- 添加列注释(标注 Control / Treatment)
- colorbar 标签"log₂(Fold Change)"
- 基因名字号 6pt
- 图片大小约 90mm x 120mm
import seaborn as sns
import pandas as pd
import numpy as np
# 使用 seaborn clustermap
g = sns.clustermap(
df_expression,
cmap='RdBu_r',
center=0,
vmin=-3, vmax=3,
figsize=(90/25.4, 120/25.4),
dendrogram_ratio=(0.15, 0.15),
cbar_kws={'label': r'$\log_2$(Fold Change)', 'shrink': 0.6},
linewidths=0.5,
linecolor='white',
xticklabels=True,
yticklabels=True,
col_colors=col_color_map, # 列注释颜色
method='ward',
metric='euclidean'
)
# 调整字体大小
g.ax_heatmap.tick_params(axis='both', labelsize=6)
g.ax_heatmap.set_xlabel('')
g.ax_heatmap.set_ylabel('')
plt.savefig('heatmap.pdf', bbox_inches='tight')
火山图(Volcano Plot)🔗
请画一张差异基因表达分析的火山图:
数据:DataFrame 包含列 'gene', 'log2FC', 'pvalue', 'padj'
阈值:|log2FC| > 1 且 padj < 0.05 为显著
要求:
- X 轴:log₂(Fold Change),Y 轴:-log₁₀(p_adj)
- 显著上调基因标红,显著下调标蓝,不显著标灰
- 标注 top 10 显著基因名(避免文字重叠,用 adjustText 库)
- 添加阈值虚线(横向和纵向)
- 在图中标注显著基因数量
- Nature 单栏宽度
import matplotlib.pyplot as plt
import numpy as np
from adjustText import adjust_text
set_publication_style()
fig, ax = plt.subplots(figsize=(89/25.4, 75/25.4))
# 分类标注
conditions = [
(df['log2FC'] > 1) & (df['padj'] < 0.05), # 显著上调
(df['log2FC'] < -1) & (df['padj'] < 0.05), # 显著下调
]
colors = ['#E64B35', '#4DBBD5', '#BFBFBF'] # 红、蓝、灰
labels = [f'Up ({conditions[0].sum()})',
f'Down ({conditions[1].sum()})',
'NS']
# 计算 -log10(padj)
df['neg_log10p'] = -np.log10(df['padj'].clip(lower=1e-300))
# 不显著的灰色点先画(在底层)
ns = ~conditions[0] & ~conditions[1]
ax.scatter(df.loc[ns, 'log2FC'], df.loc[ns, 'neg_log10p'],
c='#BFBFBF', s=3, alpha=0.5, label=f'NS ({ns.sum()})')
# 显著上调
ax.scatter(df.loc[conditions[0], 'log2FC'],
df.loc[conditions[0], 'neg_log10p'],
c='#E64B35', s=5, alpha=0.7, label=labels[0])
# 显著下调
ax.scatter(df.loc[conditions[1], 'log2FC'],
df.loc[conditions[1], 'neg_log10p'],
c='#4DBBD5', s=5, alpha=0.7, label=labels[1])
# 阈值线
ax.axhline(-np.log10(0.05), ls='--', lw=0.5, c='grey')
ax.axvline(-1, ls='--', lw=0.5, c='grey')
ax.axvline(1, ls='--', lw=0.5, c='grey')
# 标注 top 基因
sig = df[conditions[0] | conditions[1]].nlargest(10, 'neg_log10p')
texts = []
for _, row in sig.iterrows():
texts.append(ax.text(row['log2FC'], row['neg_log10p'], row['gene'],
fontsize=5, style='italic'))
adjust_text(texts, arrowprops=dict(arrowstyle='-', color='grey', lw=0.5))
ax.set_xlabel(r'$\log_2$(Fold Change)')
ax.set_ylabel(r'$-\log_{10}$(adjusted p-value)')
ax.legend(fontsize=6, loc='upper right', markerscale=1.5)
fig.savefig('volcano_plot.pdf')
plt.show()
小提琴图 / 箱线图组合🔗
请画一张展示各组数据分布的小提琴图叠加箱线图:
三组数据,用 seaborn 实现:
- 外层小提琴图展示数据分布形状
- 内层箱线图展示四分位数
- 叠加散点展示原始数据
- 添加显著性标注
Nature 单栏宽度,保存 PDF。
import seaborn as sns
import matplotlib.pyplot as plt
set_publication_style()
fig, ax = plt.subplots(figsize=(89/25.4, 65/25.4))
# 小提琴图
parts = ax.violinplot([data_ctrl, data_trtA, data_trtB],
positions=[0, 1, 2], showextrema=False)
for i, pc in enumerate(parts['bodies']):
pc.set_facecolor(colors[i])
pc.set_alpha(0.3)
# 箱线图叠加
bp = ax.boxplot([data_ctrl, data_trtA, data_trtB],
positions=[0, 1, 2], widths=0.15,
patch_artist=True, showfliers=False,
medianprops=dict(color='black', linewidth=1),
boxprops=dict(facecolor='white', linewidth=0.8))
# 散点叠加
for i, data in enumerate([data_ctrl, data_trtA, data_trtB]):
jitter = np.random.uniform(-0.05, 0.05, len(data))
ax.scatter(i + jitter, data, color=colors[i], s=10, alpha=0.6,
edgecolors='none', zorder=5)
ax.set_xticks([0, 1, 2])
ax.set_xticklabels(['Control', 'Treatment A', 'Treatment B'])
ax.set_ylabel('Expression Level')
fig.savefig('violin_box.pdf')
3.4 多子图布局(Multi-panel Figure)🔗
期刊论文中的 Figure 通常由多个子图组成。这是手动排版最头痛的部分,也是 AI 特别擅长的地方。
多子图布局 Prompt 模板:
请帮我用 matplotlib 创建一个包含 6 个子图的复合图(Figure 1):
布局:
A B C
D D E
其中面板 D 跨两列。
各面板内容:
- A: 柱状图(3 组均值对比 + 误差棒 + 显著性)
- B: 散点图(X vs Y,带线性回归拟合线和 R² 值)
- C: 箱线图(4 组数据分布)
- D: 折线图(时间序列,5 条曲线,带 SEM shade)
- E: 饼图(样本组成比例)
要求:
- 整体大小:Nature 双栏宽度(183mm),高度约 120mm
- 每个面板左上角标注 a, b, c, d, e(小写粗体,10pt)
- 统一配色方案
- 保存为 PDF
用 gridspec 实现不等宽布局的示例:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
set_publication_style()
fig = plt.figure(figsize=(183/25.4, 120/25.4))
# 创建不等宽网格
gs = gridspec.GridSpec(2, 3,
height_ratios=[1, 1],
width_ratios=[1, 1, 1],
hspace=0.35, wspace=0.35)
ax_a = fig.add_subplot(gs[0, 0]) # A: 第一行第一列
ax_b = fig.add_subplot(gs[0, 1]) # B: 第一行第二列
ax_c = fig.add_subplot(gs[0, 2]) # C: 第一行第三列
ax_d = fig.add_subplot(gs[1, 0:2]) # D: 第二行跨前两列
ax_e = fig.add_subplot(gs[1, 2]) # E: 第二行第三列
# 面板标签
for ax, label in zip([ax_a, ax_b, ax_c, ax_d, ax_e],
['a', 'b', 'c', 'd', 'e']):
ax.text(-0.15, 1.10, label, transform=ax.transAxes,
fontsize=10, fontweight='bold', va='top')
# [在每个 ax 上绑定对应内容...]
fig.savefig('Figure1.pdf')
fig.savefig('Figure1.tiff', dpi=600)
3.5 AI 辅助图表迭代优化🔗
画图是一个反复迭代的过程。利用 AI 进行迭代修改非常高效:
第一轮:生成基础图
第二轮:微调
基于上面的代码,请做以下修改:
1. X 轴标签旋转 45 度
2. Y 轴范围改为 0-5
3. 图例位置移到右上角
4. 把 Treatment_A 的颜色从蓝色改为 #00A087
5. 添加一条水平虚线标注 baseline(y=1.0)
第三轮:精修
技巧: 在 VS Code + Copilot 中,你可以选中绑定代码,用 Inline Chat(
Cmd+I)直接说"把柱状图改成水平的"或"配色改成 Science 风格",Copilot 会直接修改选中的代码。
4. 实操演示:从原始数据到发表级图表🔗
以下是一个完整的端到端工作流演示,展示如何从一份原始实验数据出发,借助 AI 完成数据清洗、统计分析和绑定。
4.1 场景设定🔗
实验背景: 你做了一个蛋白质表达量实验。用 Western Blot 定量了三组样本(Control、Drug_A、Drug_B)的目标蛋白表达水平(归一化到 β-actin),每组 6 个生物学重复。你需要分析组间差异,并制作一张适合投稿 Nature 的柱状图。
4.2 步骤 1:用 AI 生成完整分析脚本🔗
一次性大 Prompt:
请帮我完成一个完整的蛋白质表达量分析和绘图脚本。
## 实验设计
- 三组:Control (n=6), Drug_A (n=6), Drug_B (n=6)
- 测量指标:目标蛋白与 β-actin 的灰度值之比(归一化表达量)
- 数据已整理在 CSV 文件中,列为 group, expression
## 分析要求
1. 描述性统计
2. 正态性检验(Shapiro-Wilk)和方差齐性检验(Levene)
3. 根据检验结果选择合适的组间比较方法
4. 事后两两比较
5. 计算效应量(Cohen's d)
## 绘图要求
画一张 Nature 风格的柱状图:
- 单栏宽度(89mm),高度约 65mm
- 柱子颜色:灰(Control)、蓝(Drug A)、红(Drug B)
- 误差棒为 SEM
- 柱子上叠加散点(原始数据)
- 显著性标注(横线 + 星号)
- Y 轴标签:Relative Protein Expression
- 隐藏上边框和右边框
- 字体 Arial,8pt
- 保存为 PDF 和 TIFF(600 DPI)
## 结果输出
请同时打印一段英文的统计结果描述(适合直接放到论文里)。
请生成完整的 Python 脚本,包含所有必要的 import 和注释。
4.3 步骤 2:AI 生成的完整脚本🔗
以下是根据上述 Prompt,AI 通常会生成的完整脚本(已调试优化):
#!/usr/bin/env python3
"""
蛋白质表达量分析与绘图脚本
分析三组 Western Blot 定量数据,生成 Nature 风格柱状图
"""
import pandas as pd
import numpy as np
from scipy import stats
from statsmodels.stats.multicomp import pairwise_tukeyhsd
import matplotlib.pyplot as plt
import matplotlib as mpl
from itertools import combinations
# ================================================================
# 全局设置
# ================================================================
mpl.rcParams.update({
'font.family': 'Arial',
'font.size': 8,
'axes.labelsize': 8,
'axes.titlesize': 9,
'xtick.labelsize': 7,
'ytick.labelsize': 7,
'legend.fontsize': 7,
'axes.linewidth': 0.8,
'xtick.major.width': 0.8,
'ytick.major.width': 0.8,
'axes.spines.top': False,
'axes.spines.right': False,
'figure.dpi': 150,
'savefig.dpi': 300,
'savefig.bbox': 'tight',
'pdf.fonttype': 42,
'ps.fonttype': 42,
})
# Nature 风格配色
COLORS = {
'Control': '#BFBFBF',
'Drug_A': '#4DBBD5',
'Drug_B': '#E64B35'
}
# ================================================================
# 1. 读入数据
# ================================================================
df = pd.read_csv('protein_expression.csv')
print("=" * 50)
print("1. 数据概况")
print("=" * 50)
print(df.head())
print(f"\n样本量: {df.shape[0]}")
print(f"各组样本量:\n{df['group'].value_counts()}")
# ================================================================
# 2. 描述性统计
# ================================================================
print("\n" + "=" * 50)
print("2. 描述性统计")
print("=" * 50)
desc = df.groupby('group')['expression'].agg(
['count', 'mean', 'std', 'sem', 'median']
).round(4)
print(desc)
# ================================================================
# 3. 正态性检验
# ================================================================
print("\n" + "=" * 50)
print("3. Shapiro-Wilk 正态性检验")
print("=" * 50)
groups = ['Control', 'Drug_A', 'Drug_B']
group_data = {}
all_normal = True
for g in groups:
data = df[df['group'] == g]['expression'].values
group_data[g] = data
stat, p = stats.shapiro(data)
normal = "✓ 正态" if p > 0.05 else "✗ 非正态"
if p <= 0.05:
all_normal = False
print(f" {g}: W={stat:.4f}, p={p:.4f} {normal}")
# ================================================================
# 4. 方差齐性检验
# ================================================================
print("\n" + "=" * 50)
print("4. Levene 方差齐性检验")
print("=" * 50)
stat, p = stats.levene(*group_data.values())
equal_var = p > 0.05
print(f" F={stat:.4f}, p={p:.4f} {'✓ 方差齐性' if equal_var else '✗ 方差不齐'}")
# ================================================================
# 5. 组间比较
# ================================================================
print("\n" + "=" * 50)
print("5. 组间比较")
print("=" * 50)
if all_normal and equal_var:
stat, p_overall = stats.f_oneway(*group_data.values())
print(f"[One-way ANOVA] F={stat:.4f}, p={p_overall:.6f}")
test_method = "One-way ANOVA"
else:
stat, p_overall = stats.kruskal(*group_data.values())
print(f"[Kruskal-Wallis] H={stat:.4f}, p={p_overall:.6f}")
test_method = "Kruskal-Wallis"
# ================================================================
# 6. 事后多重比较
# ================================================================
pairwise_results = {}
if p_overall < 0.05:
print("\n" + "=" * 50)
print("6. 事后比较 (Tukey HSD)")
print("=" * 50)
tukey = pairwise_tukeyhsd(df['expression'], df['group'], alpha=0.05)
print(tukey)
# 提取 p 值
for i, (g1, g2) in enumerate(combinations(groups, 2)):
p_val = tukey.pvalues[i]
pairwise_results[(g1, g2)] = p_val
# ================================================================
# 7. 效应量 (Cohen's d)
# ================================================================
print("\n" + "=" * 50)
print("7. 效应量 (Cohen's d)")
print("=" * 50)
def cohens_d(a, b):
na, nb = len(a), len(b)
pooled_std = np.sqrt(((na-1)*np.std(a,ddof=1)**2 +
(nb-1)*np.std(b,ddof=1)**2) / (na+nb-2))
return (np.mean(a) - np.mean(b)) / pooled_std
for g1, g2 in combinations(groups, 2):
d = cohens_d(group_data[g1], group_data[g2])
size = "小" if abs(d) < 0.5 else ("中" if abs(d) < 0.8 else "大")
print(f" {g1} vs {g2}: d={d:.3f} ({size}效应)")
# ================================================================
# 8. 绑定
# ================================================================
print("\n" + "=" * 50)
print("8. 生成图表")
print("=" * 50)
fig, ax = plt.subplots(figsize=(89/25.4, 65/25.4))
# 柱状图
means = [group_data[g].mean() for g in groups]
sems = [stats.sem(group_data[g]) for g in groups]
x_pos = np.arange(len(groups))
bars = ax.bar(x_pos, means, yerr=sems, capsize=3,
color=[COLORS[g] for g in groups],
edgecolor='black', linewidth=0.5,
width=0.6, error_kw={'linewidth': 0.8})
# 散点叠加
for i, g in enumerate(groups):
data = group_data[g]
jitter = np.random.default_rng(42).uniform(-0.12, 0.12, len(data))
ax.scatter(i + jitter, data, color='black', s=12, alpha=0.6,
zorder=5, linewidths=0.3, edgecolors='white')
# 显著性标注
def add_sig(ax, x1, x2, y, p_val):
if p_val >= 0.05:
return # 不显著不标注
text = '***' if p_val < 0.001 else ('**' if p_val < 0.01 else '*')
h = 0.02 * (ax.get_ylim()[1] - ax.get_ylim()[0])
ax.plot([x1, x1, x2, x2], [y, y+h, y+h, y], lw=0.8, c='black')
ax.text((x1+x2)/2, y+h, text, ha='center', va='bottom', fontsize=7)
# 动态计算标注位置
y_max = max(max(group_data[g]) for g in groups)
sig_y = y_max * 1.05
for (g1, g2), p_val in pairwise_results.items():
i1, i2 = groups.index(g1), groups.index(g2)
add_sig(ax, i1, i2, sig_y, p_val)
sig_y += y_max * 0.12 # 逐级升高避免重叠
# 格式
ax.set_xticks(x_pos)
ax.set_xticklabels([g.replace('_', ' ') for g in groups])
ax.set_ylabel('Relative Protein Expression')
ax.set_ylim(0, sig_y + y_max * 0.1)
# 保存
fig.savefig('Figure_protein_expression.pdf')
fig.savefig('Figure_protein_expression.tiff', dpi=600)
print(" ✓ 已保存 Figure_protein_expression.pdf")
print(" ✓ 已保存 Figure_protein_expression.tiff (600 DPI)")
plt.show()
# ================================================================
# 9. 论文用统计描述
# ================================================================
print("\n" + "=" * 50)
print("9. 论文用统计描述(英文)")
print("=" * 50)
mean_ctrl = desc.loc['Control', 'mean']
sem_ctrl = desc.loc['Control', 'sem']
mean_a = desc.loc['Drug_A', 'mean']
sem_a = desc.loc['Drug_A', 'sem']
mean_b = desc.loc['Drug_B', 'mean']
sem_b = desc.loc['Drug_B', 'sem']
p_str = "p<0.001" if p_overall < 0.001 else f"p={p_overall:.3f}"
print(f"""
Protein expression levels were compared across three groups using
{test_method}. Drug A treatment significantly increased target protein
expression compared to the control group ({mean_a:.2f} ± {sem_a:.2f} vs
{mean_ctrl:.2f} ± {sem_ctrl:.2f}, mean ± SEM; Tukey HSD,
p={'<0.001' if pairwise_results.get(('Control','Drug_A'),1)<0.001
else f"={pairwise_results.get(('Control','Drug_A'),1):.3f}"}).
Drug B treatment showed an even greater increase ({mean_b:.2f} ± {sem_b:.2f};
p={'<0.001' if pairwise_results.get(('Control','Drug_B'),1)<0.001
else f"={pairwise_results.get(('Control','Drug_B'),1):.3f}"} vs control).
Overall {test_method}: {p_str}. All values are presented as mean ± SEM
(n=6 per group).
""")
4.4 步骤 3:运行与迭代🔗
- 首次运行:执行脚本,检查统计结果和图表
- 迭代修改:对 AI 说具体需要调整的地方
请帮我修改上面的代码:
1. Y 轴从 0 开始,不要有间断
2. 把 "Drug_A" 显示为 "Drug A (10 μM)"
3. 在图的右下角加上 "n=6" 的标注
4. 误差棒改用 SD 而不是 SEM(审稿人要求的)
4.5 常用 "一句话" 快速绘图 Prompt🔗
当你已经有了数据,只需要快速出图时:
| 需求 | 推荐 Prompt |
|---|---|
| 快速查看数据分布 | "画 df['column'] 的直方图和 QQ 图并排展示" |
| 两变量关系 | "画 X vs Y 的散点图,加线性回归拟合线,标注 R² 和 p 值" |
| 多组对比 | "画 4 组数据的箱线图 + 散点,加显著性标注" |
| 时间序列 | "画 3 条曲线的折线图,带 SEM 的阴影区域" |
| 相关性矩阵 | "画 10 个变量的 Pearson 相关性热图,只显示下三角" |
| PCA | "对 df 做 PCA,画前两个主成分的散点图,按 group 着色" |
| 生存曲线 | "画 Kaplan-Meier 生存曲线,两组对比,标注 log-rank p 值" |
5. 进阶应用🔗
5.1 用 AI 批量处理多个数据文件🔗
我有一个文件夹 ./data/,里面有 30 个 CSV 文件,命名格式为
"sample_001.csv" ~ "sample_030.csv"。
每个文件包含两列:time (s) 和 fluorescence。
请写一个脚本:
1. 批量读取所有文件
2. 对每个文件的数据做基线校正(减去前 10 个点的均值)
3. 计算所有样本的平均曲线和 SEM
4. 画一张图:淡色线条显示所有单独曲线 + 深色粗线显示平均值 + 阴影显示 SEM
5. 保存汇总数据为一个 CSV
5.2 用 AI 复现论文图表🔗
看到论文里一张好看的图想复现?直接让 AI 帮你:
请帮我用 Python 复现以下类型的图表(类似 Nature 2024 年某文章风格):
图表描述:
- 左侧是一个分组柱状图(grouped bar chart),4 个分组,每组 3 个 bar
- 右侧是一个散点图,X 轴是预测值,Y 轴是实验值,带对角线
- 两个面板并排排列,标注 a 和 b
- 颜色风格类似 Nature
请给出完整代码,用随机模拟数据演示。
5.3 数据分析自动化报告🔗
请帮我写一个 Python 脚本,自动生成数据分析报告:
1. 读取数据文件
2. 自动检测数据类型(数值型/类别型)
3. 对数值列生成描述性统计和分布图
4. 对类别列生成频率表和柱状图
5. 计算所有数值列之间的相关矩阵
6. 将所有图表和统计结果汇总到一个 PDF 报告中
使用 matplotlib 的 PdfPages 功能将多页图表保存到一个 PDF。
本章小结🔗
- ✅ 数据清洗:用详细的 Prompt 描述数据结构和问题,让 AI 生成 pandas 清洗代码;务必检查清洗前后的数据完整性
- ✅ 统计分析:根据实验设计和数据特征选择正确的统计方法;先做前提检验(正态性、方差齐性),再做主分析;报告效应量
- ✅ 科研绘图:使用标准化的全局设置(字体、字号、DPI、线宽);掌握 Nature/Science 的图片规格要求;善用 AI 迭代优化图表
- ✅ 效率工作流:一个大 Prompt 搞定"数据读取→统计分析→绘图→论文描述"全流程
- ✅ 核心原则:AI 生成的代码和统计结果必须经过你的检查和理解,不能盲目信任。特别是统计方法的选择,需要你具备基本的统计学知识
记住: AI 是你的编程加速器,不是你的大脑替代品。让 AI 写代码,你来做科学判断。
延伸阅读🔗
- Python Data Science Handbook (Jake VanderPlas)(免费在线版,全面的 pandas/matplotlib 教程)
- Seaborn Gallery(各种统计图表示例代码)
- Matplotlib Cheatsheets(速查表,打印出来贴在桌上)
- Points of Significance - Nature Methods(Nature Methods 的统计学专栏,强烈推荐)
- Ten Simple Rules for Better Figures (PLOS Comp Bio)(科研绘图的通用原则)
- ColorBrewer 2.0(在线选配色方案)
- 相关章节:VSCode Vibe Coding 教程、AI 辅助 PPT 与图表制作
参考文献🔗
-
VanderPlas, J. (2016). Python Data Science Handbook. O'Reilly Media. ↩
-
Rougier, N.P., et al. (2014). "Ten Simple Rules for Better Figures." PLOS Computational Biology, 10(9), e1003833. ↩
-
Weissgerber, T.L., et al. (2015). "Beyond Bar and Line Graphs: Time for a New Data Presentation Paradigm." PLOS Biology, 13(4), e1002128. ↩
-
Nature. "Formatting Guide: Figures." https://www.nature.com/nature/for-authors/formatting-guide ↩
-
Science. "Instructions for Authors." https://www.science.org/content/page/instructions-authors ↩