You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言中summarise与summarise_at/across加权均值结果不一致问题

问题:多列加权均值计算结果不一致的原因及正确方法

数据集

a <- data.frame(cat = c("a","b","b","c","a","c"),
           num1 = c(-2,1,2,4,3,2),
           num2 = c(-2,3,1,5,3,2),
           weight = c(3.12,2,14,1.12,1,12))

需求

计算所有含“num”字段的加权均值(实际数据集有大量此类字段)。

方法1:逐个指定列计算

a %>% summarise(num1 = weighted.mean(num1, weight, na.rm=T),
                num2 = weighted.mean(num2, weight, na.rm=T))

结果:

num1num2
1.6618531.394705

方法2:批量处理列的错误写法

写法1

a %>% summarise(across(contains("num"), ~weighted.mean(.x, na.rm=T)))

写法2

a %>% summarise_at(.vars=vars(contains("num")),
                   function(x, weight) weighted.mean(x, weight))

结果:

num1num2
1.6666672

疑问

为何两种方法结果不同?应该信任哪一种?


解答

结果不同的核心原因是批量处理的写法没有正确传递weight权重参数:

  1. 方法1的写法是正确的:weighted.mean(num1, weight, na.rm=T)明确指定了权重列weight,计算的是真正的加权均值,这个结果是可信的。
  2. 方法2的两种写法都存在参数缺失问题:
    • across的写法里,~weighted.mean(.x, na.rm=T)只传了待计算列.x和na.rm,没传权重参数w,此时weighted.mean会默认用等权重计算(也就是普通算术平均)。比如num1的算术平均是(-2+1+2+4+3+2)/6 = 1.666667,和你得到的错误结果完全匹配。
    • summarise_at的写法里,你定义的function(x, weight)需要接收weight参数,但summarise_at默认只会把待处理列x传给自定义函数,不会自动传递weight,导致权重参数缺失,同样退化为算术平均。

正确的批量处理写法

想要批量计算加权均值,必须在批量处理的函数里明确引用权重列:

推荐(tidyverse新版本语法:across)

a %>% summarise(across(contains("num"), ~weighted.mean(.x, w = weight, na.rm=T)))

旧版本语法(summarise_at)

a %>% summarise_at(.vars=vars(contains("num")),
                   ~weighted.mean(.x, w = weight, na.rm=T))

或者直接指定权重列的完整引用:

a %>% summarise_at(.vars=vars(contains("num")),
                   function(x) weighted.mean(x, w = a$weight, na.rm=T))

修正后的批量写法会得到和方法1完全一致的结果,应该信任方法1以及修正后的批量处理结果。


内容的提问来源于stack exchange,提问作者Carmen Tello

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:13:14