按组折叠数据框,使用变量列表进行加权平均和求和

Collapse data frame, by group, using lists of variables for weighted average AND sum

我想根据组折叠以下数据框,同时使用求和和加权平均值。

我有以下数据框

group_id = c(1,1,1,2,2,3,3,3,3,3)
var_1 = sample.int(20, 10)
var_2 = sample.int(20, 10)
var_percent_1 =rnorm(10,.5,.4)
var_percent_2 =rnorm(10,.5,.4)
weighting =sample.int(50, 10)

df_to_collapse = data.frame(group_id,var_1,var_2,var_percent_1,var_percent_2,weighting)

我想根据 group_id 确定的组折叠我的数据。但是,在我的数据中,我有绝对水平 (var_1var_2) 和百分比 (var_percent_1var_percent_2) 的变量。

我为每种类型的变量创建了两个列表(我的真实数据要大得多,所以这是必要的)。我还有一个加权变量(weighting)。

to_be_weighted =df_to_collapse[, 4:5]
to_be_summed = df_to_collapse[,2:3]

to_be_weighted_2=colnames(to_be_weighted)
to_be_summed_2=colnames(to_be_summed) 

我的目标是根据变量的类型(即,如果以百分比表示,我使用加权平均值)同时使用总和或加权平均值来折叠我的数据。

这是我最好的尝试:

 df_to_collapse %>% group_by(group_id) %>% summarise_at(.vars = c(to_be_summed_2,to_be_weighted_2), .funs=c(sum, mean))

但是,如您所见,它不是 加权平均值

我尝试了很多不同的方法来使用 weighted.mean 函数,但都没有成功。这是一个这样的尝试的例子;

df_to_collapse %>% group_by(group_id) %>% summarise_at(.vars = c(to_be_weighted_2,to_be_summed_2), .funs=c(weighted.mean(to_be_weighted_2, weighting), sum))

以及对应的错误:

Error in weighted.mean.default(to_be_weighted_2, weighting) : 
'x' and 'w' must have the same length

这是一种方法,通过重塑为长数据,添加一个名为 type 的虚拟变量来确定它是否是百分比(可选,但很方便),在 summarise 中应用一个函数基于无论是百分比,然后传播回宽形状。如果您可以更改列名,您可以想出一种更优雅的方式来处理 type 列,但这实际上是为了方便。

我的诀窍是 type[1] == "percent";我不得不使用 [1] 因为每个组中的所有内容都具有相同的类型,但除此之外 == 对向量中的每个值进行操作并给出多个逻辑值,当你真的只需要 1.

library(tidyverse)

set.seed(1234)
group_id = c(1,1,1,2,2,3,3,3,3,3)
var_1 = sample.int(20, 10)
var_2 = sample.int(20, 10)
var_percent_1 =rnorm(10,.5,.4)
var_percent_2 =rnorm(10,.5,.4)
weighting =sample.int(50, 10)

df_to_collapse <- data.frame(group_id,var_1,var_2,var_percent_1,var_percent_2,weighting)

df_to_collapse %>%
    gather(key = var, value = value, -group_id, -weighting) %>%
    mutate(type = ifelse(str_detect(var, "percent"), "percent", "int")) %>%
    group_by(group_id, var) %>%
    summarise(sum_or_avg = ifelse(type[1] == "percent", weighted.mean(value, weighting), sum(value))) %>%
    ungroup() %>%
    spread(key = var, value = sum_or_avg)
#> # A tibble: 3 x 5
#>   group_id var_1 var_2 var_percent_1 var_percent_2
#>      <dbl> <dbl> <dbl>         <dbl>         <dbl>
#> 1        1    26    31         0.269         0.483
#> 2        2    32    21         0.854         0.261
#> 3        3    29    49         0.461         0.262

reprex package (v0.2.0) 创建于 2018-05-04。