【问题标题】:Summarise multiple columns that have to be grouped tidyverse汇总多个必须分组的列 tidyverse
【发布时间】:2021-08-02 11:52:06
【问题描述】:

我有一个包含如下数据的数据框:

df <- data.frame(
    group1 = c("High","High","High","Low","Low","Low"),
    group2 = c("male","female","male","female","male","female"),
    one = c("yes","yes","yes","yes","no","no"), 
    two = c("no","yes","no","yes","yes","yes"), 
    three = c("yes","no","no","no","yes","yes")
)

我想总结变量onetwothree 中是/否的计数,通常我会通过df %&gt;% group_by(group1,group2,one) %&gt;% summarise(n()) 来完成。有什么方法可以汇总所有三列,然后将它们全部绑定到一个输出 df 中,而无需在每一列上手动执行代码?我尝试使用 for 循环,但我无法让 group_by() 识别我作为输入提供的列名

【问题讨论】:

  • 接受答案

标签: r tidyverse summarize


【解决方案1】:

获取长格式数据和count

library(dplyr)
library(tidyr)

df %>% pivot_longer(cols = one:three) %>% count(group1, group2, value)

#  group1 group2 value     n
#  <chr>  <chr>  <chr> <int>
#1 High   female no        1
#2 High   female yes       2
#3 High   male   no        3
#4 High   male   yes       3
#5 Low    female no        2
#6 Low    female yes       4
#7 Low    male   no        1
#8 Low    male   yes       2

【讨论】:

    【解决方案2】:

    这可以仅在dplyr 中完成(无需使用tidyr::pivot_*),但输出格式略有不同。 (即使没有rowwise,这个也可以工作,尽管我不知道它的确切原因

    df <- data.frame(
      group1 = c("High","High","High","Low","Low","Low"),
      group2 = c("male","female","male","female","male","female"),
      one = c("yes","yes","yes","yes","no","no"), 
      two = c("no","yes","no","yes","yes","yes"), 
      three = c("yes","no","no","no","yes","yes")
    )
    library(dplyr)
    
    df %>%
      group_by(group1, group2) %>%
      summarise(yes_count = sum(c_across(everything()) == 'yes'),
                no_count = sum(c_across(one:three) == 'no'), .groups = 'drop')
    #> # A tibble: 4 x 4
    #>   group1 group2 yes_count no_count
    #>   <chr>  <chr>      <int>    <int>
    #> 1 High   female         2        1
    #> 2 High   male           3        3
    #> 3 Low    female         4        2
    #> 4 Low    male           2        1
    

    reprex package (v2.0.0) 于 2021-05-12 创建

    【讨论】:

    • 原因是== 正在将其转换为逻辑向量。检查df %&gt;% group_by(group1, group2) %&gt;% summarise(new = list(c_across(everything()) == "yes")) %&gt;% pull(new)
    • 即当您执行c_across 时,它返回vector df %&gt;% group_by(group1, group2) %&gt;% summarise(new = list(c_across(everything()))) -&gt; out 现在检查outdfout$new。对于rowwise,有一个约束是它按行分组。但是,这里没有那个约束。因此,它不会在每个组的常规列中列出
    • 你也可以使用tableunnest_wider df %&gt;% group_by(group1, group2) %&gt;% summarise(count = list(table(c_across(everything()))), .groups = 'drop') %&gt;% unnest_wider(count)
    • 感谢@akrun f pi r 的解释。明白了。
    【解决方案3】:

    使用data.table

    library(data.table)
    melt(setDT(df), id.var = c('group1', 'group2'))[, .(n = .N),
        .(group1, group2, value)]
    

    -输出

        group1 group2 value n
    1:   High   male   yes 3
    2:   High female   yes 2
    3:    Low female   yes 4
    4:    Low   male    no 1
    5:    Low female    no 2
    6:   High   male    no 3
    7:    Low   male   yes 2
    8:   High female    no 1
    

    有了base R,我们可以使用bytable

    by(df[3:5], df[1:2], function(x) table(unlist(x)))
    

    【讨论】:

      猜你喜欢
      • 2020-11-24
      • 2021-06-16
      • 1970-01-01
      • 2021-11-07
      • 2020-09-14
      • 2018-03-27
      • 1970-01-01
      • 2019-09-29
      • 1970-01-01
      相关资源
      最近更新 更多