
做数据分析这么多年处理过不少重复测量设计的数据。每次跟人聊起这个主题总会碰到类似的疑问同一批对象在不同时间点测了三次数据到底是当普通方差分析做还是用重复测量方差分析这两者结论会不会不一样命令敲出来一堆结果该看哪一行这篇文章就把这件事彻底讲透。我会从概念和原理讲起说明在什么场景下必须用重复测量方差分析然后带出Stata里的完整操作命令、结果解读、常见坑位最后给零基础的朋友一条可以直接照着走的学习路径。全文用真实的案例分析贯穿所有命令都可以直接复制运行。1. 为什么普通方差分析不够用重复测量数据的特殊之处先说一个我常用来跟人解释的类比。假设你想测三个品牌的轮胎耐磨度找30辆车每10辆装一个品牌跑完同样里程后测胎纹深度。这种设计每辆车只测一次轮胎品牌是组间因素普通单因素方差分析完全够用。但换一种设计还是30辆车每辆车都依次装上三个品牌的轮胎跑相同里程后分别测胎纹深度。这时候问题来了——同一个司机、同一辆车、同一条路况测出来的三次数据之间是有相关性的。这个人的驾驶习惯激进三个轮胎磨损都偏大那个人开车佛系三个轮胎磨损都偏小。这种“个体内部的相关性”如果被忽略误差项就会被错误估计最后的F检验和p值会失真。这就是重复测量数据的核心特征观测值之间不独立。同一受试者在不同时间点或不同条件下的测量值彼此相关而这个相关性来源于个体本身的稳定性差异。普通方差分析有个基本假设叫“独立观测”重复测量数据一进来看似还像那么回事其实是“伪独立”直接拿去做普通ANOVA会出问题。重复测量方差分析Repeated Measures ANOVA的存在就是为了把个体差异这一层变异单独分离出来不再混进误差项里。这样做的好处是误差项变小了检验灵敏度更高样本量可以大幅缩减30个人就能达到普通设计60人的检验功效可以直接考察“时间与人”的交互作用这是普通设计做不到的我用一个例子说明这个差异有多大。模拟场景15名受试者在三个时间点基线、第4周、第8周测某项指标个体间差异较大。如果按普通单因素方差分析做组内变异包含了“个体差异时间效应随机误差”而按重复测量方差分析做先把每个人的均值拿出来把“个体间变异”这一大块从误差中扣除再用缩小的误差去检验时间效应。很多在普通ANOVA里不显著的时间趋势在重复测量分析里就显著了原因就在这。这个道理说白了就是“同样一个人跟自己比”比“不同的人跟别人比”要灵敏得多。医学里的血压随访、运动科学里的体能测试、营销里的消费者态度追踪都是这个逻辑的典型应用场景。2. 原理拆解方差怎么拆、F值怎么算、球形假设是什么理解了重复测量数据的特殊性再往深一层看它的数学模型和检验逻辑。这部分我尽量不堆公式用可理解的方式讲清楚背后到底发生了什么。2.1 方差分解的逻辑与个体差异分离重复测量方差分析沿用了方差分析的基本思想——把总变异拆成几块。以单因素时间因素重复测量设计为例总变异的分解如下总变异Total SS受试者间变异Between-subjects SS受试者内变异Within-subjects SS其中再拆分为时间效应变异Time SS 残差/误差变异Error SS关键的一步是“受试者间变异”被单独拿出来了。这在统计上等于先计算每个受试者多次测量的均值再看不同受试者的均值之间差距有多大。这个差距反映的是个体间的系统性差异跟时间处理无关所以不能算作“实验误差”。以受试者内自由度的计算为例如果有n名受试者、k个时间点受试者内的总自由度是n(k-1)其中时间因素占据k-1个自由度剩余的(n-1)(k-1)就是误差自由度。F值计算为[ F \frac{MS_{time}}{MS_{error}} \frac{SS_{time}/(k-1)}{SS_{error}/((n-1)(k-1))} ]在Stata里用anova命令跑完结果表里会直接列出这些项的SS、df、MS和F值。很多人只看最后一行p值我建议你养成习惯至少扫一眼SS的分配如果个体间SS占了大头恰好说明重复测量设计的选择是合理的如果个体间SS很小说明个体差异不大重复测量设计的优势就不那么明显了。2.2 球形假设重复测量方差分析的命门重复测量方差分析有一个普通方差分析没有的额外假设——球形假设Sphericity或者说复合对称性。它要求所有时间点两两之间的差异方差大致相等。用人话说测量点1和测量点2之间的分数之差其方差应该约等于测量点1和测量点3之差的方差也约等于测量点2和测量点3之差的方差。这三个“差值方差”如果相差太大说明有些时间段的变化幅度波动剧烈而有些时间段相对稳定此时标准F检验就不再可靠。违反球形假设的后果是F值被高估p值偏小也就是说更容易出现“假阳性结论”。本来不该显著的结果看起来显著了。这在做重复测量分析时是最常见的陷阱务必记得查看球形检验Mauchlys test的结果或在Stata里使用自动修正的选项。Stata中anova命令后接repeated()选项时会自动输出球形检验及三种修正后的结果。我后面会在操作部分详细演示。2.3 三种修正Greenhouse-Geisser、Huynh-Feldt和Lower-bound当球形假设被违反时主流统计学软件会给出修正后的p值。三种修正方法的核心思路都一样——给自由度打个折扣让F检验的临界值变大p值变大从而纠正虚假的显著性。Greenhouse-GeisserG-G修正最保守的一种用εepsilon衡量球形性的偏离程度。ε最大为1完全球形最小为1/(k-1)严重违反。ε越小修正幅度越大自由度被压缩得越狠p值越难显著。Huynh-FeldtH-F修正比G-G温和一些。G-G在高样本量时可能过度保守H-F就派上用场了。Lower-bound修正最极端保守直接把自由度放到最小一般用得少。实操中选哪个经验法则是当Mauchly检验结果为违反球形时看G-G的ε值如果ε0.75倾向于用H-F修正如果ε0.75用G-G修正。而最稳妥的做法是当检验结果冲突或边界模糊时直接报告两种修正的p值结论一致性更强时更让人放心。3. 适用情形与设计版本什么时候用它怎么判断明白了原理接下来这一节特别重要因为我见过太多人拿着设计不当的数据跑来问为什么结果奇怪。先把适用情形搞清楚了操作才谈得上意义。3.1 典型适用场景重复测量方差分析通常用在这些场景时间追踪研究同一组患者在治疗前、治疗中、治疗后的各项指标变化多条件同一受试者研究同一受试者接受全部处理水平如不同剂量的药物、不同教学方法空间/位置重复同一台机器的多个部位、同一批材料的多个样本点的测量纵向发展研究儿童在不同年龄段的认知能力测评排除标准也很简单如果每个受试者只接受一种处理、只测一次数据那就用普通方差分析或协方差分析别硬套重复测量。3.2 三种设计版本搞清楚重复测量方差分析有三种常见形式很多人在第一步就混淆了。版本一单因素重复测量One-way RM-ANOVA只有一个组内因素通常就是时间所有受试者都在每个水平下测一次。比如15个人分别在三个时间点测血压。版本二双因素混合设计Mixed-design ANOVA既有组间因素又有组内因素。比如30名受试者分成实验组和对照组每组都随访三个月、每个月测一次指标。组间因素是“分组”组内因素是“时间”。这种设计在临床试验里最常用也是能产出最多信息的设计。版本三多因素重复测量组内因素不止一个。比如受试者在“上午/下午”和“运动前/运动后”两个维度上都有重复测量。这种设计越来越复杂阶乘设计让交互项非常多解读难度也成倍增加。新手我建议先从版本一和版本二开始。3.3 判断流程一张决策清单当你拿到一批数据不知道怎么选择模型时按下面这个顺序过一次每个受试者是否被测量了多次如果不是——普通ANOVA或t检验多次测量的时间点或条件是否相同比如都是0周、4周、8周——如果是可以做重复测量是否有分组因素没有——单因素重复测量有——混合设计是否存在缺失数据不完整数据会影响重复测量分析必要时需要先处理缺失或使用混合模型有没有协变量需要控制有的话考虑ANCOVA扩展这套判断流程基本能覆盖大多数实际场景。如果你发现自己手里的数据是“不同的人测量的时间点不一致”比如有些人随访到3个月有些人随访到6个月还有的中间流失了那恭喜你已经超越了重复测量方差分析的适用范围该去了解混合效应模型了。4. 操作命令实现从数据整理到完整Stata代码理论部分讲了不少现在进入实际操作环节。我用一个完整的模拟案例逐步演示在Stata里完成重复测量方差分析的全过程。4.1 案例数据说明与产生沿用前面的例子一家健康管理机构想评估某种饮食干预8周的效果。招募了15名志愿者分别在第0周基线、第4周、第8周测量体重公斤。其中第1-8号受试者实行干预饮食干预组第9-15号受试者正常饮食对照组。这是非常典型的2×3混合设计。在Stata里模拟这批数据很简单clear set seed 20250214 set obs 15 gen id _n gen group 1 if id 8 replace group 0 if id 8 label define grp 0 对照组 1 干预组 label values group grp gen base rnormal(75, 8) group*(-1) // 基线体重干预组略低 gen week4 base rnormal(-1.5, 2) group*(-2) // 4周变化干预组多降一些 gen week8 base rnormal(-2.5, 3) group*(-3.5) // 8周变化干预组降幅更大 list id group base week4 week8 in 1/6, sepby(group)数据现在是宽的wide format一行一个人三列分别是三个时间点的体重。Stata的anova命令做重复测量分析可以直接用宽格式但如果你后面要扩展分析混合模型长格式long format更方便。4.2 宽格式转换与数据管理把宽数据转成长期望格式的方法是用reshape命令这是Stata数据管理里必须掌握的技能之一reshape long base week4 week8, i(id) j(time)等等这样写不对。reshape long的正确用法是先指定前缀、再指定时间变量但base、week4、week8的前缀各不相同无法一次性reshape。所以常用的做法是先统一变量名// 更稳妥的转换方法 gen t0 base gen t1 week4 gen t2 week8 keep id group t0 t1 t2 reshape long t, i(id) j(time) rename t weight label define time 0 基线 1 第4周 2 第8周 label values time time list id group time weight in 1/12, sepby(id)转换好之后每一行是一个“人-时间点”观测总共15×345条记录。长格式的好处在于它可以混合使用不同水平的模型命令比如mixed也可以非常方便地画折线图和交互图。4.3 单因素重复测量方差分析命令详解先做单因素版本仅看全部15人的时间趋势暂时忽略分组。使用anova命令配合repeated()选项anova weight id time, repeated(time)结果输出表中会有一个关键部分——球形检验和修正后的p值。很多初学者看到一个大表就懵了。我建议你盯着这么几行时间效应的F值和p值Mauchlys W统计量、p值Greenhouse-Geisser epsilon和Huynh-Feldt epsilon修正后的显著性如果不知道正版命令要怎么做可以用anova的完整写法anova weight id time, repeated(time) class(id)class(id)告诉Stataid是分类变量受试者编号repeated(time)指定了组内因素。另一种做法是使用repeated命令的力推者——manova它内部就处理了重复测量的问题。但anova命令更直接也更接近新手的学习曲线。4.4 混合设计重复测量方差分析完整命令现在加入分组因素考察“分组×时间”的交互。命令如下anova weight group / id|group time group#time, repeated(time)这行命令是这个分析的核心务必记下来。它做的事情是group组间因素检验干预组和对照组的总体均值差异/ id|group嵌套在组内的受试者随机效应这就是把“个体差异”抽出来的关键time组内时间因素检验时间主效应group#time组与时间的交互检验两组下降趋势是否不同运行后的输出表会按来源分层显示SS、df、MS、F、p值。简要说明怎么解读group行两组是否有显著差异time行随时间推移所有人的体重是否有显著变化group#time行两组之间随时间变化的趋势是否有差异。这一行往往是研究最关心的结果——如果显著说明干预效果确实存在且随时间推移而显现在anova命令后加入repeated(time)Stata会自动补充球形检验输出。4.5 使用mixed命令作为现代替代最近这几年我更倾向于建议有一定基础的读者直接用mixed混合效应模型来做重复测量数据尤其是数据有缺失时。原因在于重复测量方差分析要求“完整数据矩形”——只要有一个时间点缺失那个人就被整行删掉很浪费。而混合模型利用的是所有有效的数据点。对应上面的混合设计mixed命令可以写为mixed weight group##time || id:, reml这个命令的含义非常清晰固定效应部分是group#time的完整展开随机效应部分|| id:表示每个受试者都有自己的随机截距。结果输出里固定效应部分的系数表可以直接解读group系数干预组基线时与对照组的差异time系数对照组随时间的斜率group#time交互系数干预组的额外变化量用mixed模型的好处是它不依赖球形假设所以也就不需要做G-G修正。缺点是对新手来说模型输出的解读比anova多一层门槛。我的经验是如果你是在做学术报告或发表论文结构方程/混合模型是主流方法如果你只是快速看数据走势、做探索性分析anova的经典三重表主效应、交互效应、球形修正输出更直接。5. 结果解读拿到输出后怎么看、怎么报告命令跑完只是完成了第一步大部分人的困难在于面对一张密密麻麻的结果表时不知如何下嘴。这一节我带你把anova的关键输出逐行过一遍并示范学术报告的标准写法。5.1 anova核心结果解读以我们的案例数据为例典型的输出会包含这三块第一块是方差分析表Number of obs 45 R-squared 0.XXXX Root MSE X.XXXX Source | Partial SS df MS F Prob F -------------------------------------- Model | ... group | ... id|group| ... time | ... group#time | ... Residual| ...第二块是球形检验Test of Sphericity Mauchlys W 0.XXX Approx. chi-square X.XX, df 2, p 0.XXX Greenhouse-Geisser epsilon 0.XXX Huynh-Feldt epsilon 0.XXX Lower-bound epsilon 0.XXX第三块是修正后的F检验| F df Prob F Time | X.XX (2, XX) p X.XXX Time (G-G) | X.XX (X.XX, XX.XX) p X.XXX Time (H-F) | X.XX (X.XX, XX.XX) p X.XXX解读优先级我建议这样排第一步看Mauchly检验的p值。若p0.05球形假设成立直接用第一行未修正的F和p结果若p0.05使用G-G或H-F修正后的结果。第二步看交互项group#time的p值。这个值有多重要它告诉你两组人的变化轨迹是否一致。如果p0.05恭喜你找到了一个有效干预信号——但别急着下结论最好再做后续简单效应分析后面会讲。第三步再看主效应。这里有个常见的坑当交互显著时主效应可能具有误导性。比如两组变化的趋势相反平均后时间主效应可能被抵消。主效应和交互效应同时显著时解读的重点应放在交互上。第四步看id|group这一项的SS和p值。此项体现了受试者间的随机差异Stata的anova表会给出F检验。如果这个F值显著说明个体间的基线差异大重复测量设计捕获了这部分变异模型选择是对的。如果不显著反而值得你重新审视设计是否合理。5.2 事后检验与简单效应分析在重复测量框架下“事后检验”和“简单效应”这两个概念常被混用但它们解决的问题不一样。事后检验Post-hoc发现时间主效应显著想知道具体哪两个时间点之间差异显著。比如基线vs第4周、基线vs第8周、第4周vs第8周。简单效应Simple effects在交互显著时想知道在某个时间点上两组差异是否显著或者在某个组内时间趋势是否显著。Stata在anova后直接加margins和pwcompare就能实现// 时间的事后两两比较 margins time, pwcompare(effects) mcompare(bonferroni) // 交互的简单效应按时间点比较组间差异 margins group, at(time(0 1 2)) pwcompare(effects) mcompare(bonferroni)输出结果中每组比较都有对应的对比值、标准误、t值和调整后的p值。用Bonferroni调整是相对保守的选择它把显著性水平按比较次数做除法。比较次数少的时候可以用比较次数多比如超过6次我建议改用Sidak或FDR控制方法避免过度的负效应导致真实差异被掩盖。5.3 学术报告的标准写法示范结果部分要写成什么样子给一个模板采用2分组干预组、对照组× 3时间基线、第4周、第8周重复测量方差分析其中分组为组间因素时间为组内因素。Mauchly球形检验结果显示W 0.XXp 0.XXX数据满足/违反了球形假设因此报告G-G修正后的结果ε 0.XXX。结果显示时间主效应显著F(2, 26) X.XX, p 0.XXX说明体重随时间显著下降分组主效应不显著F(1, 13) X.XX, p 0.XXX分组与时间的交互效应显著F(2, 26) X.XX, p 0.XXX表明干预组和对照组的体重变化轨迹存在显著差异。进一步简单效应分析发现干预组在基线与第8周之间的体重差异显著MD X.XX kg, p 0.XXX而对照组的变化不显著MD X.XX kg, p 0.XXX。这段写的核心思路是交代设计、交代球形检验、报告修正依据、依次报告三个效应、补充事后结果。审稿人看到这样的写法会觉得作者对方法是有理解的不是盲目套命令。6. 实操中的七个坑位这些错误我几乎每年都会遇到这一节我专门把实操中常见的错误和注意事项集中起来讲。这些不是从教科书里抄来的是真实跑数据时反复踩过的坑。6.1 数据长宽格式搞反anova做重复测量分析很特殊它接受的是宽格式数据——一行一个受试者、一列一个时间点。如果你手里的数据是长格式直接跑anova结果会完全错误因为Stata会把每一行当成一个独立观测。如果要跑mixed模型则必须用长格式。所以建议的工作流程是原始数据往往是一行一个受试者的大宽表先整理好宽格式用anova跑完后把分析所需的几个变量用reshape long转换成长期望格式再把mixed跑一遍。两种模型的结果可以互相对照验证结论的稳健性。6.2 忽略球形假设的修正这是最典型的一个坑。新手拿到anova输出直接看第一行F和p值就写结论。但如果Mauchly检验显示p0.05第一行的结果就是不可靠的。我见过一篇待审稿件时间效应第一行p0.035作者差点就写成显著了。但G-G修正后p0.072结论完全反转。差之毫厘结论谬以千里。所以在查看结果的第一时间就该明确“修正后的p值”和“未修正的p值”报告哪一种取决于球形检验。6.3 缺失数据的处理策略不对重复测量数据最常见的痛点是失访、漏测、设备故障带来的缺失值。经典anova遇到缺失会使用列表删除——只要有任何一个时间点缺失这个人所有的数据都被剔除。样本量本来就不大的时候这种处理方式太浪费了。应对措施有如果缺失比例很低5%而且完全随机缺失可以补充插补后继续用anova如果缺失比例较高或存在规律性缺失强烈建议改用mixed模型它本质上是处理不平衡数据的方法不要求完整数据插补的方法也要讲究不要盲目用均值填补。简单的线性插值在时间序列数据里其实表现尚可但使用任何插补方法都应该做敏感性分析。6.4 受试者编号被当作连续变量处理不少小白在构建模型时会把id变量直接放进模型忘了声明分类变量。Stata默认把数值型变量当连续变量处理结果模型会把“受试者编号”当成一个有线性效应的协变量来拟合——完全没有任何意义。正确做法是用class(id)声明或者用xi前缀又或者直接确保id已经被encode成类别变量。上面的anova命令里我特意写了class(id)不是多余的。6.5 交互显著后只报主效应假设你跑混合设计发现group#time交互显著结果报告里却只写“时间显著”“分组显著”这样的报告逻辑上是有缺陷的。交互显著意味着主效应的解释是不完整的——两个主效应可能被交互作用所“掩盖”或“歪曲”。正确的思路是先看交互显著与否。交互显著则主效应退居次位继续做简单效应分析。交互不显著再报告主效应。这个顺序不能颠倒。6.6 事后检验没有做多重比较校正时间点一多两两比较的次数就会快速上升。3个时间点有3对比较4个时间点就有6对5个时间点就有10对。比较次数越多纯靠运气发现“显著”的可能性也越大。Stata的pwcompare命令默认不做校正需要手动指定mcompare(bonferroni)或mcompare(sidak)。我一般建议至少用Sidak它在多数情况下比Bonferroni温和一些但依然能有效控制族系错误率。6.7 样本量和效应量没有预估这个坑不在操作层面但在研究设计层面——而且很致命。重复测量设计的功效分析跟普通设计差别很大需要单独考虑时间点之间的相关性。相关性越高检测同一效应所需的样本量就越小这是重复测量设计的红利但有些人不知道这个红利直接套用普通ANOVA的样本量计算方式导致样本量要么偏大浪费经费要么偏小没有功效。Stata官方有power repeated命令可以做一些基础的样本量和功效计算但复杂的设置建议使用专门软件如G*Power辅助确定。7. 零基础Stata学习路径从装软件到独立完成重复测量分析最后这一节是专门给零基础的朋友看的。很多人留言问我“我完全没学过统计能学会Stata做重复测量方差分析吗”——我的答案是能但要有路径和方法。统计软件学习不像背单词它是“用中学”的过程。下面这条路径是我这些年带新人总结出来的你按顺序走下来完成重复测量方差分析不是问题。7.1 第一阶段Stata基础操作与数据管理约两周安装好Stata后第一个任务不是学统计命令而是熟悉基本界面和数据管理逻辑。需要掌握的几项核心技能打开和保存数据文件.dta、Excel导入导出变量创建与生成generate、replace、recode数据筛选与排序keep、drop、sort、by数据合并merge与追加append长宽数据转换reshape这个阶段最容易犯的错误是把大量时间花在“系统的菜单操作”上我建议从一开始就逐步熟悉do文件的使用习惯。每跑一个操作都把代码写在do文件里保存起来。这比点菜单高效太多——做完一个项目do文件本身就是你的分析日志。练习建议找一个Excel表格数据集手工清洗整理转成长格式。这个过程多重复几次数据手感就能训练出来。7.2 第二阶段描述统计与绘图约一周有了干净数据之后就要学会“看数据”。掌握summarize、tabstat、table等描述统计命令以及histogram、boxplot、twoway line等绘图。在重复测量分析的上下文中尤其要会画“个体时序图”和“分组均值趋势图”。画分组均值趋势图可以直观地看到两组变化轨迹跟后面交互效应的结果互相对照collapse (mean) mean_weightweight (sd) sd_weightweight, by(group time) twoway (connected mean_weight time if group0, lcolor(blue) mcolor(blue)) /// (connected mean_weight time if group1, lcolor(red) mcolor(red)), /// legend(label(1 对照组) label(2 干预组)) /// xtitle(时间点) ytitle(体重(kg)) name(fig1, replace)这张图会让你在跑正式检验之前就对结果有一个预判。7.3 第三阶段统计推断基础两周到一个月重复测量方差分析本质上仍是方差分析大家族的一员所以基础方差分析的逻辑必须先掌握。建议按这个顺序推进t检验配对t检验和非配对t检验都要会单因素方差分析双因素方差分析协方差分析ANCOVA重复测量方差分析重点理解球形假设每个知识点都配合Stata的命令去跑实际数据。统计理论不需要你退到数学系的深度理解方差分解的基本思想就够用。7.4 第四阶段深入学习与批判性使用长期等到你能独立完成重复测量方差分析之后建议再去拓展几个关联方向它们能在你数据分析的道路上帮上大忙混合效应模型mixed弥补重复测量方差分析的不足处理缺失数据能力强广义估计方程GEE人群平均效应的估计尤其适合流行病学随访数据结构方程建模SEM处理潜变量和重复测量数据的整合我的建议是非科班出身的人不一定要吃透所有模型的数学推导但至少要理解每个模型“解决什么问题”“在什么条件下使用”“结果怎么解读”。分析数据的过程本质上就是不断回答这三个问题的过程。统计学习最忌讳的就是“先背命令后补原理”。命令操作属于表层技能两三个星期就能练熟但理解了方差分解逻辑和球形假设的原理之后遇到新的设计变体比如三因素重复测量、非平衡设计也能迁移应用。先懂道理再动命令这条路走起来慢一点但每一步都算数。