首页 > 解决方案 > 使用基于行的过滤器进行多项操作的汇总

问题描述

我有一个df应该用于根据a group_by单个列()的条目计算多个条目的以下比率(除法cond3):

cond1 cond2 cond3 value
foo   oof   A     1
foo   oof   B     2
foo   oof   D     3
foo   bar   A     1
foo   bar   B     2
foo   bar   C     4
foo   bar   D     4
buz   oof   A     2
buz   oof   C     1
buz   oof   B     3
bar   rab   C     3
bar   rab   B     4  
bar   rab   D     2 

我可以为单个选择完成此操作并按如下方式除以另一个:

df %>% group_by(cond1, cond2) %>% 
  summarise(ratio = value[cond3 == "A"] / value[cond3 == "B"])

现在,假设我有两个列表,例如:

list1 <- c("A","C")
list2 <- c("B","D")

我想对多个组合进行除法。这可以像这样明确地完成:

    df %>% group_by(cond1, cond2) %>% 
      summarise(ratio_AB = value[cond3 == "A"] / value[cond3 == "B"],
ratio_AD = value[cond3 == "A"] / value[cond3 == "D"],
ratio_CB = value[cond3 == "C"] / value[cond3 == "B"],
ratio_CD = value[cond3 == "C"] / value[cond3 == "D"])

我想像伪循环一样隐式完成:

df %>% group_by(cond1, cond2) %>% 
  summarise(ratios = value[cond3 %in% list1] / value[cond3 %in% list2])

没有平均值的预期输出:

   cond1 cond2 ratio_AB ratio_AD ratio_CB ratio_CD
 1 foo   oof   0.5      0.67     NA       NA 
 2 foo   bar   0.5      0.25     2        1
 3 buz   oof   0.67     NA       0.67     NA 
 4 bar   rab   NA       NA       0.75     1.5 

注意:这是基于我的示例。完整的 df 将包含所有四个条件 ( A,B,C,D),因此不需要任何NA值。

后者显然行不通。如果我想避免嵌套汇总操作的循环,我将如何处理?

标签: rdplyr

解决方案


我们从 'list1'、'list2' 创建一个组合数据集crossing,用于循环行,通过在子集后创建 'ratio_' 列pmap对原始数据集 'df' 通过 'cond1'、'cond2'进行分组summarise基于“cond3”上的组合数据集的“值”并将reduce它们与单个数据集full_join

library(dplyr)
library(tidyr)
library(purrr)
library(stringr)
crossing(list1, list2) %>%
   pmap(~ df %>% 
            group_by(cond1, cond2) %>%
            summarise(!! str_c('ratio_', ..1, ..2) :=
                 value[cond3 == ..1]/value[cond3 == ..2], .groups = 'drop')) %>% 
   reduce(full_join, by = c('cond1', 'cond2'))

-输出

# A tibble: 4 x 6
#  cond1 cond2 ratio_AB ratio_AD ratio_CB ratio_CD
#  <chr> <chr>    <dbl>    <dbl>    <dbl>    <dbl>
#1 buz   oof      0.667   NA        0.333     NA  
#2 foo   bar      0.5      0.25     2          1  
#3 foo   oof      0.5      0.333   NA         NA  
#4 bar   rab     NA       NA        0.75       1.5

赋值运算符的!!lhs 是评估创建的字符串str_c以分配为列名。通常,当我们用 进行赋值时=,lhs 将是不带​​引号的列名,而在 中base R,我们使用setNameswithpaste来创建新的列名


推荐阅读