统计方法怎么选
跟完这篇,您能拿着自己的数据,用一套三步判断法在几分钟内定位到该用哪种统计方法,照着走一个完整例子,并知道对应的 R 函数怎么写。
做统计最常卡住的不是「不会跑」,而是「不知道该跑哪个」。其实绝大多数常规分析,都能靠三个问题定位到一两种方法。这篇不堆公式,只给您一套可照着走的判断流程、一个从头走到尾的例子,外加一张速查表。选定方法之后,具体怎么做、怎么读结果,可以再看对应的专题教程。
先问三件事
拿到数据,别急着套检验。先回答下面三个问题,答案基本就把方法范围锁死了。
第一件:您的数据是什么类型?
- 计量(连续)数据:能取小数、有大小和间距,如表达量、浓度、身高、血压。
- 计数数据:非负整数,如某段时间内的事件次数、reads 数、菌落数。
- 分类数据:只分组别,如「有效/无效」「基因型 AA/Aa/aa」。二分类是最常见的一种。
判断类型时看的是因变量(您想解释、想比较的那个结果),不是分组变量。
第二件:您想干什么?
- 比组间差异:几组之间某个指标有没有不同(如给药组 vs 对照组)。
- 看关系:两个变量是不是一起变(相关),或用一个变量去解释/预测另一个(回归)。
- 看生存/到事件时间:关心「多久之后发生某事件」,且有些样本还没发生就随访结束了(删失)。
第三件:几组、是否配对?
- 几组:两组和三组以上,走的方法不一样。
- 是否配对/重复测量:同一批对象在不同条件下各测一次(如用药前后同一个人、同一样本两种处理),属于配对,要用配对版方法,不能当成两组独立样本硬比。
把这三件事的答案记在手边,下面每一节都按它们来分岔。
照着走一个例子
先用一个常见场景把三步走一遍,您就知道这套判断法怎么落地。
场景:您有 30 个样本,测了某基因的表达量,分「给药组」和「对照组」两组(不同的样本,不是同一批测两次),想看两组表达量有没有差异。
按三步定位:
- 数据类型:因变量是表达量,能取小数、有大小 → 连续数据。
- 想干什么:比较两组的这个指标 → 组间比较。
- 几组、是否配对:两组,且是不同样本 → 两组、独立。
三步走完,方法范围就锁在「两组、连续、独立」这一格。再补一个动作——看分布是否近似正态,就能在 t 检验和 Wilcoxon 之间定夺:
# 第一步:看因变量分布是否近似正态
hist(df$expr)
qqnorm(df$expr); qqline(df$expr)
shapiro.test(df$expr)
# 第二步:近似正态就用 t 检验,明显偏离就用 Wilcoxon(二选一)
t.test(expr ~ group, data = df) # 近似正态
wilcox.test(expr ~ group, data = df) # 明显偏离正态或有强离群
结论:这份数据是「两组独立、连续」,方法就在两样本 t 检验和 Wilcoxon 秩和检验之间二选一,由正态判断定夺——一件事就做完了。换成别的数据,也是同一套走法,只是落到不同的格子。下面各节把每个格子展开写清楚。
组间比较怎么选
这是最常见的场景:比较不同组的某个连续指标。分岔点是几组和是否满足正态。
先说一个惯例:连续数据在每组样本量不大时,通常先看它是否大致服从正态分布,再决定用参数还是非参数方法。这是常用惯例、非铁律——检验对轻度偏离并不敏感,样本量大时更稳健。
判断正态的常规做法,看这三样就够:
| 看什么 | 怎么看 | 怎么判断 |
|---|---|---|
| 分布形状 | 直方图 hist() | 大致对称、单峰即可 |
| 分位对齐 | QQ 图 qqnorm() + qqline() | 点基本贴着参考线 |
| 辅助检验 | Shapiro-Wilk shapiro.test() | p 小提示偏离,但样本量很大时会过度敏感,别只看它 |
# 直观看:直方图 + QQ 图
hist(df$value)
qqnorm(df$value); qqline(df$value)
# 辅助检验:Shapiro-Wilk(p 小提示偏离正态,样本量很大时会过度敏感,别只看它)
shapiro.test(df$value)
看的是每组内部的分布,不是把两组混在一起看。判断好正态与否,再按「几组 + 是否配对」选:
两组比较
# 两组独立、近似正态:两样本 t 检验
# R 的 t.test 默认用 Welch 校正(var.equal = FALSE),不要求两组方差相等,可放心用
t.test(value ~ group, data = df)
# 两组独立、不满足正态或有明显离群:Wilcoxon 秩和检验(即 Mann-Whitney U)
wilcox.test(value ~ group, data = df)
# 配对设计(如用药前后同一批对象):数据为宽表,前后各一列,每行一个对象
t.test(df$before, df$after, paired = TRUE) # 配对 t 检验
wilcox.test(df$before, df$after, paired = TRUE) # Wilcoxon 符号秩检验
两组比较的更多细节(前提假设、单双侧、方差齐性)见 t 检验还是非参数检验。
三组及以上
# 各组近似正态:单因素方差分析 ANOVA
fit <- aov(value ~ group, data = df)
summary(fit)
# 若 ANOVA 显著,再做两两比较(事后检验)
TukeyHSD(fit)
# 不满足正态:Kruskal-Wallis 检验(ANOVA 的非参数对应)
kruskal.test(value ~ group, data = df)
注意一个常被忽略的点:多组时不要把它们两两拆开、反复做 t 检验——那会放大假阳性。正确做法是先用 ANOVA/Kruskal-Wallis 做整体检验,显著后再做配套的事后比较,并对多重比较做校正。这背后的原理见 多重检验校正。
分类结果的比较
如果您比的不是连续指标,而是「比例」(如两组的有效率),那是分类对分类,用卡方或 Fisher:
tab <- table(df$group, df$outcome)
chisq.test(tab) # 常规列联表(2×2 时 R 默认做连续性校正)
fisher.test(tab) # 样本量小、期望频数偏低时更稳妥
惯例:当列联表里期望频数 <5 的格子较多时,优先用 Fisher 精确检验——这是常用经验界线、非铁律,按数据规模灵活判断。
看关系:相关还是回归
两个变量「有没有关系」和「谁解释谁」,是两类不同的问题。
相关:只想知道两个连续变量是不是一起变、方向如何,不区分谁是因谁是果。
# 线性关系、近似正态:Pearson 相关
cor.test(df$x, df$y, method = "pearson")
# 单调但非线性,或有离群、非正态:Spearman 秩相关
cor.test(df$x, df$y, method = "spearman")
相关系数只说「一起变的强度和方向」,不等于因果,也不能用来预测。
回归:想用一个或多个自变量去解释、预测因变量,或在控制其他因素后看某个因素的独立作用。按因变量类型选模型:
| 因变量类型 | 模型 | R 写法 |
|---|---|---|
| 连续 | 线性回归 | lm(y ~ x1 + x2, data = df) |
| 二分类(是/否) | 逻辑回归 | glm(y ~ x1 + x2, family = binomial, data = df) |
| 计数 | 泊松/负二项回归 | glm(y ~ x, family = poisson, data = df) |
fit <- lm(y ~ x1 + x2, data = df)
summary(fit) # 看系数、p 值、R²
计数数据用泊松回归时,如果方差明显大于均值(过度离散),按惯例改用负二项回归(MASS::glm.nb())更稳妥。
一句话记忆:只想看两者关联强弱,用相关;想解释、想控制混杂、想预测,用回归。
生存分析怎么选
生存分析针对「到事件发生的时间」,核心特点是存在删失(随访结束时事件还没发生,或对象中途失访)。它需要两列:时间 time 和状态 status(1=发生事件,0=删失)。别用普通 t 检验或回归硬套。
分岔很简单,看您要描述/比较还是建模:
Kaplan-Meier(KM)+ Log-rank:画生存曲线、比较少数几组的生存差异。
library(survival)
fit <- survfit(Surv(time, status) ~ group, data = df)
plot(fit) # KM 生存曲线
survdiff(Surv(time, status) ~ group, data = df) # Log-rank 检验,比较组间差异
Cox 比例风险模型:要同时纳入多个因素(含连续变量)、控制混杂、得到风险比 HR。
cox <- coxph(Surv(time, status) ~ group + age + stage, data = df)
summary(cox) # 看 HR(exp(coef))、置信区间、p 值
一句话:分组画曲线、比差异用 KM+Log-rank;要多因素校正、算 HR 用 Cox。 Cox 有一个「比例风险」前提假设需要检查,展开做法见 生存分析:KM 曲线与 log-rank 检验。
报告时别漏了这些
选对方法只是第一步。报告结果时,按惯例还应交代:
- 用了哪种方法、为什么(如「因不满足正态,改用 Wilcoxon 秩和检验」);
- 效应量,而不只是 p 值:p 值只说「有没有差异」,差异有多大要靠均值差、HR、相关系数、置信区间等来说;
- 是否做了多重比较校正:一次分析里比了很多次时尤其重要;
- 前提假设是否满足、样本量、缺失值如何处理。
这些不是形式,而是让别人(和几个月后的您自己)能判断结论可不可信。方法各有适用边界,如实写清「为什么这么选、在什么条件下成立」,比追求一个漂亮的 p 值更重要。
一张速查表
把上面的分岔浓缩成一张表,遇到新数据时按「目的 + 数据类型 + 组数」查一行即可。表里的方法是常规首选,具体仍要结合数据分布和研究设计判断。
| 目的 | 数据/条件 | 首选方法 | R 函数 |
|---|---|---|---|
| 两组比较 | 连续、近似正态 | 两样本 t 检验 | t.test() |
| 两组比较 | 连续、非正态 | Wilcoxon 秩和检验 | wilcox.test() |
| 两组比较 | 连续、配对 | 配对 t/符号秩检验 | t.test(paired=TRUE) / wilcox.test(paired=TRUE) |
| 多组比较 | 连续、近似正态 | 单因素 ANOVA(+事后检验) | aov() + TukeyHSD() |
| 多组比较 | 连续、非正态 | Kruskal-Wallis | kruskal.test() |
| 比例比较 | 分类 × 分类 | 卡方 / Fisher 精确 | chisq.test() / fisher.test() |
| 看关联 | 两连续、线性正态 | Pearson 相关 | cor.test(method="pearson") |
| 看关联 | 两连续、单调非正态 | Spearman 相关 | cor.test(method="spearman") |
| 解释/预测 | 因变量连续 | 线性回归 | lm() |
| 解释/预测 | 因变量二分类 | 逻辑回归 | glm(family=binomial) |
| 解释/预测 | 因变量计数 | 泊松/负二项回归 | glm(family=poisson) |
| 生存差异 | 分组、有删失 | KM 曲线 + Log-rank | survfit() + survdiff() |
| 生存建模 | 多因素、有删失 | Cox 比例风险模型 | coxph() |
表中的正态、方差齐性等条件是常用惯例、非铁律:检验对轻度偏离并不敏感,样本量、离群值、研究设计都会影响判断。拿不准时,非参数方法通常更稳妥。
在平台上跑一遍
如果您暂时不想纠结代码,在百沐一下的「智能统计」里可以零代码完成这一步:上传数据表,用一句话说清目的(如「比较三组表达量是否有显著差异」),系统会替您判断该用哪种检验、跑出结果,并给出可复现的 R 代码;分组列、是否配对这类关键处,它会先跟您确认,选错也能追问着改。
去试试:https://app.baimuyixia.com,或先看 智能统计使用指南。