首页 > 解决方案 > weighted.mean, summarise() 和 cross()

问题描述

我想按数字聚合以下数据框(变量 y 和 z)并按“权重”加权。这工作如下:

df = data.frame(number=c("a","a","a","b","c","c"), y=c(1,2,3,4,1,7),
                z=c(2,2,6,8,9,1), weight =c(1,1,3,1,2,1))


aggregate = df %>%
  group_by(number) %>%
  summarise_at(vars(y,z), funs(weighted.mean(. , w=weight)))

由于 summarise_at 不应再使用,因此我尝试使用它。但我没有成功:

aggregate = df %>%
  group_by(number) %>%
  summarise(across(everything(), list( mean = mean, sd = sd)))

# this works for mean but I can't just change it with "weighted.mean" etc.


标签: r

解决方案


我们可以通过匿名函数~。通过检查summarise_at,OP 只想返回列 'y'、'z' 的摘要,即 usingeverything()也会返回mean和'weight' 列sdweighted.mean这没有多大意义

library(dplyr)
df %>%
  group_by(number) %>%
   summarise(across(c(y, z), 
   list( mean = mean, sd = sd,
            weighted = ~weighted.mean(., w = weight))), .groups = 'drop')
# A tibble: 3 x 7
#  number y_mean  y_sd y_weighted z_mean  z_sd z_weighted
#  <chr>   <dbl> <dbl>      <dbl>  <dbl> <dbl>      <dbl>
#1 a           2  1           2.4   3.33  2.31       4.4 
#2 b           4 NA           4     8    NA          8   
#3 c           4  4.24        3     5     5.66       6.33

通常,meanandsd在没有NA元素时效果很好。但是如果有NA值,我们可能需要使用na.rm = TRUE(默认情况下它是FALSE. 在这种情况下,lambda 调用对于传递额外的参数很有用

df %>%
  group_by(number) %>%
   summarise(across(c(y, z), 
   list( mean = ~mean(., na.rm = TRUE), sd = ~sd(., na.rm = TRUE),
            weighted = ~weighted.mean(., w = weight))), .groups = 'drop')

推荐阅读