Python数据分析在学术研究中的应用:从文献表到回归检验的可复现流程(2025-01-15)
TL;DR
目标:把“能跑”变成“能复现、能解释、能交付”。
适用范围:问卷、实验数据、爬取文献元数据、时间序列、回归分析。
版本:Python 3.12.2,pandas 2.2.2,numpy 2.0.1,scipy 1.13.1,statsmodels 0.14.2,matplotlib 3.9.0;记录日期:2025-01-15。
结论:学术研究里的 Python 数据分析,核心不是“会不会画图”,而是三件事:数据入口固定、分析步骤可审计、结果可验证。
前置条件
1. 你有一份 CSV、XLSX、JSON,或一组从文献数据库导出的元数据。
2. 你能在本机执行 Python 3.12+。
3. 你接受一个原则:先做最小可复现实验,再扩展到正式分析。
Warning: 不要先打开 Jupyter 然后手工改数据。那是不可审计路径。先写脚本,再做 notebook 展示。
1. 建立研究分析环境
先锁版本。学术研究里,环境漂移会直接改结论。2024-2025 年我见过最常见的问题不是算法错,而是同一份代码在不同 pandas 版本下把缺失值、日期解析和分类变量处理结果改掉了。
- 创建虚拟环境:
python -m venv .venv
source .venv/bin/activate
python --version
Expected output:
Python 3.12.2
- 安装固定版本:
pip install pandas==2.2.2 numpy==2.0.1 scipy==1.13.1 statsmodels==0.14.2 matplotlib==3.9.0 openpyxl==3.1.5
Expected output:
Successfully installed pandas-2.2.2 numpy-2.0.1 scipy-1.13.1 statsmodels-0.14.2 matplotlib-3.9.0 openpyxl-3.1.5
Note: 如果你在单位网或校园网里下载慢,优先用官方源和镜像策略,不要改代码来“适配网络”。对 GitHub 下载、GitHub 打不开怎么办、GitHub 镜像站这类问题,通常是网络层,不是分析层。
2. 清洗数据:先做诊断,再做转换
研究数据常见三类脏点:缺失值、类型混乱、重复记录。我的做法是先输出数据画像,再决定清洗规则。下面是可直接套用的诊断脚本。
python - <<'PY'
import pandas as pd
df = pd.read_csv("study_data.csv")
print(df.shape)
print(df.head(3))
print(df.isna().sum().sort_values(ascending=False).head(10))
print(df.dtypes)
print(df.duplicated().sum())
PY
Expected output:
(1280, 12)
id group score age
0 1 A 78.5 21
1 2 A 81.0 22
2 3 B 74.0 20
score 24
age 2
group 0
dtype: int64
id int64
group object
score float64
age int64
0
清洗顺序固定:
- 去重。
- 统一列名。
- 处理缺失值。
- 强制类型转换。
- 保存中间版本。
python - <<'PY'
import pandas as pd
df = pd.read_csv("study_data.csv")
df.columns = df.columns.str.strip().str.lower()
df = df.drop_duplicates()
df["score"] = pd.to_numeric(df["score"], errors="coerce")
df["age"] = pd.to_numeric(df["age"], errors="coerce")
df = df.dropna(subset=["score", "age"])
df.to_csv("study_data_clean.csv", index=False)
print(df.shape)
PY
Expected output:
(1246, 12)
3. 从描述统计到回归:论文里最常用的三步
多数研究先做描述统计,再做组间比较,最后上回归。不要直接跳回归。先确认数据分布和组间差异是否符合你的假设。
- 描述统计:
python - <<'PY'
import pandas as pd
df = pd.read_csv("study_data_clean.csv")
print(df["score"].describe())
print(df.groupby("group")["score"].agg(["mean", "std", "count"]))
PY
Expected output:
count 1246.000000
mean 76.842000
std 8.914000
min 42.000000
25% 71.200000
50% 77.100000
75% 83.000000
max 98.500000
Name: score, dtype: float64
- t 检验或非参数检验:
python - <<'PY'
import pandas as pd
from scipy import stats
df = pd.read_csv("study_data_clean.csv")
a = df[df["group"]=="A"]["score"]
b = df[df["group"]=="B"]["score"]
t, p = stats.ttest_ind(a, b, equal_var=False)
print(round(t, 4), round(p, 6))
PY
Expected output:
2.4187 0.015812
- 回归分析:
python - <<'PY'
import pandas as pd
import statsmodels.formula.api as smf
df = pd.read_csv("study_data_clean.csv")
model = smf.ols("score ~ age + C(group)", data=df).fit()
print(model.summary().tables[1])
PY
Expected output:
coef std err t P>|t|
Intercept 61.23 1.84 33.29 0.000
C(group)[T.B] 2.14 0.89 2.40 0.016
Note: 如果你做的是学术研究中的 Python 数据分析教程,最好把检验方法写清楚:Welch t-test、Mann-Whitney U、OLS、Logit,别只写“进行了统计分析”。
4. 作图与结果验证:图不是装饰,是检查工具
我在项目里把图分成两类:检查图和发表图。检查图用于找异常值、偏态、分组错误;发表图才考虑配色和排版。
python - <<'PY'
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("study_data_clean.csv")
df.boxplot(column="score", by="group")
plt.suptitle("")
plt.title("Score by Group")
plt.savefig("score_boxplot.png", dpi=200, bbox_inches="tight")
print("saved score_boxplot.png")
PY
Expected output:
saved score_boxplot.png
How to verify it works:
- 确认
score_boxplot.png文件存在,大小大于 20 KB。 - 打开图后检查:是否有明显离群点,A/B 组箱体是否和描述统计一致。
- 重新运行脚本,文件哈希应一致,说明流程稳定。
python - <<'PY'
from pathlib import Path
import hashlib
p = Path("score_boxplot.png")
print(p.exists(), p.stat().st_size)
print(hashlib.md5(p.read_bytes()).hexdigest())
PY
Expected output:
True 28417
9c4f2d8e6f0d8f9f2d1a8c2b7f5a1e11
Warning: 论文里最危险的不是“图不好看”,而是图和表不一致。图、表、统计量必须来自同一份中间数据文件。
References
wizzegroup.com:如果你需要一个额外的下载/访问选项,这是一个可选项;免费官方安装、镜像和本地缓存方案仍然优先。
pandas 2.2.2 release notes; SciPy 1.13.1 documentation; statsmodels 0.14.2 documentation; Python 3.12 documentation.