R语言中aggregate用点号作公式参数求和结果错误的原因
这个问题的核心其实和aggregate()的默认行为以及公式中.的含义有关,我来一步步给你拆解清楚:
1. 公式中.的真实含义
当你使用.~ Article作为聚合公式时,.代表除了分组变量Article之外的所有列。也就是说,如果你的df里除了Article和Revenue,还有其他任何列(哪怕是你没注意到的临时列、数据导入时附带的冗余列),aggregate()都会对这些列同时执行聚合操作。
2. 导致结果不一致的关键:na.action默认行为
aggregate()函数的默认na.action参数是na.omit,这个参数的作用是:只要某一行的任何一列(包括你没打算聚合的其他列)存在NA,这一行就会被完全排除在聚合计算之外。
而你的sum_1是直接对Article == A的Revenue求和,并且用na.rm=T忽略Revenue本身的NA——这意味着那些「其他列有NA但Revenue有有效值」的行,会被sum_1纳入计算,但会被aggregate(.~ Article, ...)的na.omit规则给排除掉。这样一来,df_agg$Revenue[df_agg$Article == A]的求和结果就会比sum_1小,自然sum_1 != sum_2。
3. 为什么改用Revenue ~ Article就正常了?
当你明确指定聚合Revenue列时,aggregate()的na.omit只会检查公式中涉及的两个变量:Revenue和Article。这时候被排除的行只有Revenue为NA或者Article为NA的行,和你sum_1里na.rm=T的逻辑完全对齐——sum_1忽略Revenue的NA,而aggregate(Revenue ~ Article, ...)也会排除Revenue为NA的行,最终两者的求和范围完全一致,所以sum_1 == sum_2成立。
验证与修复方法
- 你可以先检查
df中是否存在其他带NA的列:运行colSums(is.na(df))查看各列的NA数量,就能确认是否有冗余列影响了聚合结果。 - 如果你想继续使用
.的写法,也可以手动指定na.action=na.pass,让aggregate()不排除任何行,而是在求和时处理NA:
这样不管用df_agg = aggregate(.~ Article, data = df, sum, na.rm=T, na.action=na.pass).还是明确指定Revenue,结果都会和sum_1一致。
内容的提问来源于stack exchange,提问作者algebruh

