【问题标题】:weighted mean in dplyr for multiple columnsdplyr 中多列的加权平均值
【发布时间】:2017-09-22 00:14:55
【问题描述】:

我正在尝试使用 dplyr 计算多列的加权平均值。目前我坚持使用summarize_each,这对我来说似乎是解决方案的一部分。这是一些示例代码:

library(dplyr)
f2a <- c(1,0,0,1)
f2b <- c(0,0,0,1)
f2c <- c(1,1,1,1)
clustervar <- c("A","B","B","A")
weight <- c(10,20,30,40)

df <- data.frame (f2a, f2b, f2c, clustervar, weight, stringsAsFactors=FALSE)
df

我正在寻找的是类似的东西

df %>%
  group_by (clustervar) %>%
  summarise_each(funs(weighted.mean(weight)), select=cbind(clustervar, f2a:f2c))

这样的结果只有:

# A tibble: 2 × 4
  clustervar select4 select5 select6
       <chr>   <dbl>   <dbl>   <dbl>
1          A      25      25      25
2          B      25      25      25

我在这里错过了什么?

【问题讨论】:

    标签: r dplyr mean weighted


    【解决方案1】:

    您可以使用summarise_at 指定要操作的列:

    df %>% group_by(clustervar) %>% 
        summarise_at(vars(starts_with('f2')), 
                     funs(weighted.mean(., weight)))
    #> # A tibble: 2 × 4
    #>   clustervar   f2a   f2b   f2c
    #>        <chr> <dbl> <dbl> <dbl>
    #> 1          A     1   0.8     1
    #> 2          B     0   0.0     1
    

    【讨论】:

    • 谢谢阿利斯泰尔!为了好玩,我也错过了 .
    【解决方案2】:

    我们可以将其重塑为“长”格式,然后执行此操作

    library(tidyverse)
    gather(df, Var, Val, f2a:f2c) %>% 
            group_by(clustervar, Var) %>% 
            summarise(wt =weighted.mean(Val, weight)) %>%
            spread(Var, wt)
    

    或者另一种选择是

    df %>%
        group_by(clustervar) %>% 
        summarise_each(funs(weighted.mean(., weight)), matches("^f"))
    # A tibble: 2 × 4     
    #    clustervar   f2a   f2b   f2c
    #         <chr> <dbl> <dbl> <dbl>
    # 1          A     1   0.8     1
    # 2          B     0   0.0     1
    

    或者使用summarise_atmatches(另一个帖子的另一个变体 - 发帖时没有看到其他帖子)

    df %>% 
       group_by(clustervar) %>% 
       summarise_at(vars(matches('f2')), funs(weighted.mean(., weight)))
    # A tibble: 2 × 4
    #   clustervar   f2a   f2b   f2c
    #        <chr> <dbl> <dbl> <dbl>
    #1          A     1   0.8     1
    #2          B     0   0.0     1
    

    或者另一个选项是data.table

    library(data.table)
    setDT(df)[, lapply(.SD, function(x) weighted.mean(x, weight)),
                           by = clustervar, .SDcols  = f2a:f2c]
    #    clustervar f2a f2b f2c
    #1:          A   1 0.8   1
    #2:          B   0 0.0   1
    

    注意:所有四个答案都基于合法的tidyverse/data.table 语法,并且会得到预期的输出

    我们还可以创建一个使用 dplyr 开发版(即将发布 0.6.0)的语法的函数。 enquo 通过获取输入参数并将其转换为 quosures 来完成类似的替代工作。在 group_by/summarise/mutate 中,我们通过取消引用(UQ 或 !!)来评估 quosure

    wtFun <- function(dat, pat, wtcol, grpcol){
           wtcol <- enquo(wtcol)
           grpcol <- enquo(grpcol)
           dat %>%
               group_by(!!grpcol) %>%
               summarise_at(vars(matches(pat)), funs(weighted.mean(., !!wtcol)))
     }
    
    wtFun(df, "f2", weight, clustervar)
    # A tibble: 2 × 4
    #   clustervar   f2a   f2b   f2c
    #       <chr> <dbl> <dbl> <dbl>
    #1          A     1   0.8     1
    #2          B     0   0.0     1
    

    【讨论】:

    • 请不要删除投反对票的答案只是为了重新发布它们以试图清除反对票。这被认为是对系统的滥用,是不可接受的。 See here 了解更多。
    猜你喜欢
    • 2015-04-28
    • 2021-09-03
    • 2018-07-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 2019-01-28
    • 2021-09-21
    • 2017-08-16
    相关资源
    最近更新 更多