dplyr中多列的加权平均值

时间:2017-04-25 06:11:35

标签: r dplyr mean weighted

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

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

结果只是:

 <script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script>

我在这里缺少什么?

2 个答案:

答案 0 :(得分:15)

您可以使用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

答案 1 :(得分:-1)

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

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语法,并且会获得预期的输出

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

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