【问题标题】:Multiple ratios by column-wise division with dplyr following grouping分组后使用 dplyr 逐列除法的多个比率
【发布时间】:2021-04-07 19:08:09
【问题描述】:

我有一个 df 需要按多列分组,以便随后计算不同列子集的比率以及逐行均值和标准差。

grouper1 grouper2 condition value
foo      baz      A         1
foo      baz      B         2
foo      oof      A         1
foo      oof      C         3
bar      zab      B         2
bar      zab      C         4

基于这个优雅的answer,我设法构建了一个通用解决方案:

library(dplyr)
library(tidyr)
library(purrr)
library(stringr)


crossing(c("A"), c("B","C")) %>%
  pmap(~ query %>%
         group_by(grouper1, grouper2) %>%
            summarise(!! str_c('ratio_', ..1, ..2) :=
                 value[condition == ..1]/value[condition == ..2])) %>% 
            reduce(full_join, by = c('grouper1', 'grouper2')) %>% 
  ungroup() %>% mutate(mean=rowMeans(select(.,-(grouper1, grouper2)), SD=unlist(pmap(select(.,-(grouper1, grouper2)), ~sd(c(...)))))

如果在所有组中都找到condition 列中的所有值,则此方法效果很好。如果不是这种情况,例如A 在上例中使用grouper1 的第二个分组中不存在,我将收到以下错误:

Error: Column ratio_AC must be length 1 (a summary value), not 0

我显然可以预先选择 crossing 的值,但这需要在 df 上进行过滤,我将失去一般性。因此,我想要一个简单地忽略缺失组合并仍然计算指标的解决方案。

一个可能的解决方案是pivot_wider,但在这里我无法实现一个可行的解决方案来计算比率。

【问题讨论】:

    标签: r dplyr tidyr


    【解决方案1】:

    我们可以使用pivot_wider 重塑为宽格式,然后使用该数据集

    library(dplyr)
    library(tidyr)
    library(purrr)
    library(stringr)
    df1 <- df %>% 
              pivot_wider(names_from = condition, values_from = value)
    
    
    crossing(v1 = c("A"), v2 = c("B","C")) %>%
      pmap(~ df1 %>%           
               transmute(grouper1, grouper2, 
              !! str_c('ratio_', ..1, ..2) :=
                     .[[..1]]/.[[..2]]))%>% 
                reduce(full_join, by = c('grouper1', 'grouper2'))  %>%
       mutate(mean = rowMeans(select(., -grouper1, -grouper2), na.rm = TRUE), 
              SD=   pmap_dbl(select(., -grouper1, -grouper2), 
                  ~sd(c(...), na.rm = TRUE)))
    

    数据

    df <- structure(list(grouper1 = c("foo", "foo", "foo", "foo", "bar", 
    "bar"), grouper2 = c("baz", "baz", "oof", "oof", "zab", "zab"
    ), condition = c("A", "B", "A", "C", "B", "C"), value = c(1L, 
    2L, 1L, 3L, 2L, 4L)), class = "data.frame", row.names = c(NA, 
    -6L))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-23
      • 2023-02-07
      • 1970-01-01
      相关资源
      最近更新 更多