【问题标题】:dplyr summarise : Group by multiple variables in a loop and add results in the same dataframedplyr summarise :在循环中按多个变量分组并将结果添加到同一数据框中
【发布时间】:2021-12-24 20:07:32
【问题描述】:

我想计算几个变量的不同模式的指标,然后将这些结果添加到单个数据框中。我可以用几个summarise 加上group_by 毫无问题地做到这一点,然后做一个rbind 来收集结果。下面,我对 hdv2003 数据(来自 questionr 包)进行处理,并在变量 'sexe'、'trav.satisf' 和 'cuisine' 上创建了 rbind 结果。

library(questionr)
library(tidyverse)
data(hdv2003)

tmp_sexe <- hdv2003 %>%
  group_by(sexe) %>%  
  summarise(n = n(),
            percent = round((n()/nrow(hdv2003))*100, digits = 1),
            femmes = round((sum(sexe == "Femme", na.rm = TRUE)/sum(!is.na(sexe)))*100, digits = 1),
            age = round(mean(age, na.rm = TRUE), digits = 1)
  )

names(tmp_sexe)[1] <- "group"

tmp_trav.satisf <- hdv2003 %>%
  group_by(trav.satisf) %>%  
  summarise(n = n(),
            percent = round((n()/nrow(hdv2003))*100, digits = 1),
            femmes = round((sum(sexe == "Femme", na.rm = TRUE)/sum(!is.na(sexe)))*100, digits = 1),
            age = round(mean(age, na.rm = TRUE), digits = 1)
  )

names(tmp_trav.satisf)[1] <- "group"

tmp_cuisine <- hdv2003 %>%
  group_by(cuisine) %>%  
  summarise(n = n(),
            percent = round((n()/nrow(hdv2003))*100, digits = 1),
            femmes = round((sum(sexe == "Femme", na.rm = TRUE)/sum(!is.na(sexe)))*100, digits = 1),
            age = round(mean(age, na.rm = TRUE), digits = 1)
  )

names(tmp_cuisine)[1] <- "group"

synthese <- rbind (tmp_sexe,
                   tmp_trav.satisf,
                   tmp_cuisine)

结果如下:

# A tibble: 8 x 5
  group              n percent femmes   age
  <fct>          <int>   <dbl>  <dbl> <dbl>
1 Homme            899    45      0    48.2
2 Femme           1101    55    100    48.2
3 Satisfaction     480    24     51.5  41.4
4 Insatisfaction   117     5.9   47.9  40.3
5 Equilibre        451    22.6   49.9  40.9
6 NA               952    47.6   60.2  56  
7 Non             1119    56     43.8  50.1
8 Oui              881    44     69.4  45.6

问题是这篇文章太长而且难以管理。所以我想用 for 循环产生相同的结果。但是我在R中的循环有很多麻烦,我做不到。这是我的尝试:

groups <- c("sexe",
            "trav.satisf",
            "cuisine")

synthese <- tibble()

for (i in seq_along(groups)) {
  tmp <- hdv2003 %>%
    group_by(!!groups[i]) %>%  
    summarise(n = n(),
              percent = round((n()/nrow(hdv2003))*100, digits = 1),
              femmes = round((sum(sexe == "Femme", na.rm = TRUE)/sum(!is.na(sexe)))*100, digits = 1),
              age = round(mean(age, na.rm = TRUE), digits = 1)
    )
  
  names(tmp)[1] <- "group"
  synthese <- bind_rows(synthese, tmp)
}

它有效,但没有产生预期的结果,我不明白为什么:

# A tibble: 3 x 5
  group           n percent femmes   age
  <chr>       <int>   <dbl>  <dbl> <dbl>
1 sexe         2000     100     55  48.2
2 trav.satisf  2000     100     55  48.2
3 cuisine      2000     100     55  48.2

【问题讨论】:

    标签: r for-loop dplyr group-by summarize


    【解决方案1】:
    library(questionr)
    library(tidyverse)
    data(hdv2003)
    
    list("trav.satisf", "cuisine", "sexe") %>%
      map(~ {
        hdv2003 %>%
          group_by_at(.x) %>%
          summarise(
            n = n(),
            percent = round((n() / nrow(hdv2003)) * 100, digits = 1),
            femmes = round((sum(sexe == "Femme", na.rm = TRUE) / sum(!is.na(sexe))) * 100, digits = 1),
            age = round(mean(age, na.rm = TRUE), digits = 1)
          ) %>%
          rename_at(1, ~"group") %>%
          mutate(grouping = .x)
      }) %>%
      bind_rows() %>%
      select(grouping, group, everything())
    #> # A tibble: 8 x 6
    #>   grouping    group              n percent femmes   age
    #>   <chr>       <fct>          <int>   <dbl>  <dbl> <dbl>
    #> 1 trav.satisf Satisfaction     480    24     51.5  41.4
    #> 2 trav.satisf Insatisfaction   117     5.9   47.9  40.3
    #> 3 trav.satisf Equilibre        451    22.6   49.9  40.9
    #> 4 trav.satisf <NA>             952    47.6   60.2  56  
    #> 5 cuisine     Non             1119    56     43.8  50.1
    #> 6 cuisine     Oui              881    44     69.4  45.6
    #> 7 sexe        Homme            899    45      0    48.2
    #> 8 sexe        Femme           1101    55    100    48.2
    

    reprex package (v2.0.1) 于 2021 年 11 月 12 日创建

    【讨论】:

    • 非常感谢,我真的需要学习咕噜声!你知道为什么我的 for 循环解决方案不起作用吗?
    • for 循环失败,因为您必须使用group_by(!!sym(groups[i]))group_by_at(groups[i])。您的 for 循环等效于 group_by("foo"),它始终是包含所有行的一组。在r4ds.had.co.nz 有一本免费的书来学习这些 tiodyverse 函数。
    • 好的,我的脚本现在可以使用 group_by_at。但我不明白group_bygroup_by_at 之间的区别。在我的第一个示例(没有循环)中,group_by 产生了几行,而不仅仅是一个 ?为什么它与循环不同?
    • 看看foo &lt;- "foo"; tibble(x = seq(3)) %&gt;% group_by(!!foo)
    • 我不明白。无论如何,我必须阅读更多相关信息,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-19
    • 1970-01-01
    相关资源
    最近更新 更多