使用tidyverse按组和总体获取摘要

4

我正在尝试使用 dplyr 一步获取按组别和整体的汇总统计数据,例如平均值等。

#Data set-up
sex <- sample(c("M", "F"), size=100, replace=TRUE)
age <- rnorm(n=100, mean=20 + 4*(sex=="F"), sd=0.1)
dsn <- data.frame(sex, age)


library("tidyverse")

#Using dplyr to get means by group and overall
mean_by_sex <- dsn %>% 
  group_by(sex) %>% 
  summarise(mean_age = mean(age))

mean_all <- dsn %>% 
  summarise(mean_age = mean(age)) %>% 
  add_column(sex = "All")

#combining the results by groups and overall
final_result <- rbind(mean_by_sex, mean_all)
final_result  
#> # A tibble: 3 x 2
#>   sex   mean_age
#>   <fct>    <dbl>
#> 1 F         24.0
#> 2 M         20.0
#> 3 All       21.9
#This is the table I want but I wonder if is the only way to do this

有没有使用 tidyverse 和 dplyr 中的 group_by_at 或 group_by_all 函数等类似函数来缩短这个步骤的方法?非常感谢您的帮助。

1
类似于:https://dev59.com/Il0Z5IYBdhLWcg3wtSE8(实际上没有比您使用的更好的答案)或另一种选择:https://dev59.com/SpHea4cB1Zd3GeqPsKhm - MrFlick
https://cran.r-project.org/package=tables 包可以在一行代码中完成这个任务:library(tables); tabular(sex + 1 ~ age * mean, dsn) - G. Grothendieck
3个回答

3

也许一个选项是:

dsn %>%
 group_by(sex) %>%
 summarise(mean_age = mean(age)) %>%
 add_row(sex = "ALL", mean_age = mean(dsn$age))

  sex   mean_age
  <fct>    <dbl>
1 F         24.0
2 M         20.0
3 ALL       21.9

2
稍微进行一些变更也可以实现这一点。
final_result <- dsn %>% 
  add_row(sex = "All", age = mean(age)) %>% 
  group_by(sex) %>% 
  summarise(mean_age = mean(age))

我们几乎同时发布了相同的内容 :) 但是,有一个重大区别:如果年龄不在全局环境中,你的解决方案将无法工作。 - tmfmnk
谢谢@vanao veneri。我稍微修改了代码,现在它可以工作了。 - SimRock

0

如果您只需要一个变量进行总结,那么这些答案非常好。但是如果有两个呢?我想要在一个变量上进行总结,而保留另一个变量的原始值。由于数据框仍然需要被分组,因此上述解决方案在这种情况下无法使用。

#Data set up 
set.seed(3243242)
dsn <- tibble(
  obese = sample(c(TRUE, FALSE), size=100, replace = TRUE),
  sex = sample(c("M", "F"), size=100, replace=TRUE),
                  age = rnorm(n=100, mean=20 + 4*(sex=="F"), sd=0.1)
                    )
library("tidyverse")

我使用了两个 group_by 变量重新阐述了原始问题。

#Extend to 2 group_by variables?
df1 <- dsn %>%
  group_by(sex, obese) %>% 
  summarise(mean_age = mean(age)) %>%
  ungroup() 

#Also across sex
df2 <- dsn %>%
  group_by(obese) %>% 
  summarise(mean_age = mean(age)) %>%
  ungroup() 

#Final_result:
bind_rows(df1, df2)

有一步完成的方法吗?您可以使用add_row()mean添加,但不能用于分组的df。另一种选择是创建一个函数,在组数据集上执行所有操作。如果您想要做其他事情,如排序或创建新变量,则可以在函数中完成。然后,您可以将该函数应用到每个分组数据集。通过dplyr :: bind_rows()组合后,您可以通过tidyr :: replace_na()将缺少的组变量更改为全部。

  #'@param df_group A grouped tibble
find_summary <- function(df_group){
  df_group %>% 
summarize(mean_age = mean(age))  #add other dplyr verbs here as needed like arrange or mutate
}

bind_rows(
    find_summary(group_by(dsn, sex, obese)),
    find_summary(group_by(dsn, obese))
    ) %>%
     replace_na(list(sex = "all"))

sex   obese mean_age
  <chr> <lgl>    <dbl>
1 F     FALSE     24.0
2 F     TRUE      24.0
3 M     FALSE     20.0
4 M     TRUE      20.0
5 all   FALSE     21.7
6 all   TRUE      22.3

如果你想要所有变量的总结,可以通过一个变量和两个变量来扩展这个想法。

bind_rows(
    find_summary(group_by(dsn, sex, obese)),
    find_summary(group_by(dsn, obese)),
    find_summary(dsn)
    ) %>%
     replace_na(list(sex = "all", obese = "all"))

  sex   obese mean_age
  <chr> <chr>    <dbl>
1 F     FALSE     24.0
2 F     TRUE      24.0
3 M     FALSE     20.0
4 M     TRUE      20.0
5 all   FALSE     21.7
6 all   TRUE      22.3
7 all   all       22.0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接