在 dplyr 中使用不同的分组变量进行总结
Summarize using different grouping variables in dplyr
我想为我希望执行的每个摘要使用不同的分组变量来总结一个数据框。例如,我有三个变量(x1、x2、x3)。我想按 x1 对数据帧进行分组并获取该组中的观察数,但我想对 x2 和 x3 执行相同的操作。
我想用同一块管道来完成这个,但到目前为止我想出的唯一解决方案是为我想要的每个单独的分组保存多个输出。
要重现我的数据框:
x1 <- c(0,1,1,2,2,3,3,3,4,4,5,6,6,7,8,9,9,10)
x2 <- c(0,0,1,1,0,1,2,0,0,2,1,0,3,4,2,3,0,3)
x3 <- c(0,1,0,1,2,2,1,3,4,2,4,6,3,3,6,6,9,7)
df <- data.frame(x1,x2,x3)
我的预期输出看起来像这样,其中 x 是变量的最小和最大数量,n_x1-3 是特定数量的观察数量并将该变量用作分组变量:
x n_x1 n_x2 n_x3
1 0 1 7 2
2 1 2 4 3
3 2 2 3 3
4 3 3 3 3
5 4 2 1 2
6 5 1 NA NA
7 6 2 NA 3
8 7 1 NA 1
9 8 1 NA NA
10 9 2 NA 1
11 10 1 NA NA
到目前为止,我已经想出了对每个变量单独进行汇总和分组,然后作为最后一步将它们连接在一起。
x1_count <- df %>%
group_by(x1) %>%
summarise(n_x1=n())
x2_count <- df %>%
group_by(x2) %>%
summarise(n_x2=n())
x3_count <- df %>%
group_by(x3) %>%
summarise(n_x3=n())
all_count <- full_join(x1_count, x2_count,
by=c("x1"="x2")) %>%
full_join(., x3_count,
by=c("x1"="x3")) %>%
rename("x"="x1")
是否有某种解决方法可以让我不必输出多个数据帧然后将它们连接在一起。我更喜欢更干净更优雅的解决方案。
我们可以使用简单的 map
和 full_join
library(dplyr)
library(purrr)
map(names(df), ~ df %>%
count(!!rlang::sym(.x)) %>%
rename_at(1, ~ 'x')) %>%
reduce(full_join, by = 'x') %>%
rename_at(-1, ~ str_c('n_x', seq_along(.)))
# x n_x1 n_x2 n_x3
#1 0 1 7 2
#2 1 2 4 3
#3 2 2 3 3
#4 3 3 3 3
#5 4 2 1 2
#6 5 1 NA NA
#7 6 2 NA 3
#8 7 1 NA 1
#9 8 1 NA NA
#10 9 2 NA 1
#11 10 1 NA NA
或者使用一个简单的base R
选项
t(table(c(col(df)), unlist(df)))
一个简单的 tidyr 解决方案
library(tidyr)
df %>%
pivot_longer(everything(),names_to="variables",values_to="values") %>%
group_by(variables,values) %>%
summarize(n_x=n()) %>%
ungroup() %>%
pivot_wider(names_from = variables,values_from=n_x)
# A tibble: 11 x 4
values x1 x2 x3
<dbl> <int> <int> <int>
1 0 1 7 2
2 1 2 4 3
3 2 2 3 3
4 3 3 3 3
5 4 2 1 2
6 5 1 NA NA
7 6 2 NA 3
8 7 1 NA 1
9 8 1 NA NA
10 9 2 NA 1
11 10 1 NA NA
我想为我希望执行的每个摘要使用不同的分组变量来总结一个数据框。例如,我有三个变量(x1、x2、x3)。我想按 x1 对数据帧进行分组并获取该组中的观察数,但我想对 x2 和 x3 执行相同的操作。
我想用同一块管道来完成这个,但到目前为止我想出的唯一解决方案是为我想要的每个单独的分组保存多个输出。
要重现我的数据框:
x1 <- c(0,1,1,2,2,3,3,3,4,4,5,6,6,7,8,9,9,10)
x2 <- c(0,0,1,1,0,1,2,0,0,2,1,0,3,4,2,3,0,3)
x3 <- c(0,1,0,1,2,2,1,3,4,2,4,6,3,3,6,6,9,7)
df <- data.frame(x1,x2,x3)
我的预期输出看起来像这样,其中 x 是变量的最小和最大数量,n_x1-3 是特定数量的观察数量并将该变量用作分组变量:
x n_x1 n_x2 n_x3
1 0 1 7 2
2 1 2 4 3
3 2 2 3 3
4 3 3 3 3
5 4 2 1 2
6 5 1 NA NA
7 6 2 NA 3
8 7 1 NA 1
9 8 1 NA NA
10 9 2 NA 1
11 10 1 NA NA
到目前为止,我已经想出了对每个变量单独进行汇总和分组,然后作为最后一步将它们连接在一起。
x1_count <- df %>%
group_by(x1) %>%
summarise(n_x1=n())
x2_count <- df %>%
group_by(x2) %>%
summarise(n_x2=n())
x3_count <- df %>%
group_by(x3) %>%
summarise(n_x3=n())
all_count <- full_join(x1_count, x2_count,
by=c("x1"="x2")) %>%
full_join(., x3_count,
by=c("x1"="x3")) %>%
rename("x"="x1")
是否有某种解决方法可以让我不必输出多个数据帧然后将它们连接在一起。我更喜欢更干净更优雅的解决方案。
我们可以使用简单的 map
和 full_join
library(dplyr)
library(purrr)
map(names(df), ~ df %>%
count(!!rlang::sym(.x)) %>%
rename_at(1, ~ 'x')) %>%
reduce(full_join, by = 'x') %>%
rename_at(-1, ~ str_c('n_x', seq_along(.)))
# x n_x1 n_x2 n_x3
#1 0 1 7 2
#2 1 2 4 3
#3 2 2 3 3
#4 3 3 3 3
#5 4 2 1 2
#6 5 1 NA NA
#7 6 2 NA 3
#8 7 1 NA 1
#9 8 1 NA NA
#10 9 2 NA 1
#11 10 1 NA NA
或者使用一个简单的base R
选项
t(table(c(col(df)), unlist(df)))
一个简单的 tidyr 解决方案
library(tidyr)
df %>%
pivot_longer(everything(),names_to="variables",values_to="values") %>%
group_by(variables,values) %>%
summarize(n_x=n()) %>%
ungroup() %>%
pivot_wider(names_from = variables,values_from=n_x)
# A tibble: 11 x 4
values x1 x2 x3
<dbl> <int> <int> <int>
1 0 1 7 2
2 1 2 4 3
3 2 2 3 3
4 3 3 3 3
5 4 2 1 2
6 5 1 NA NA
7 6 2 NA 3
8 7 1 NA 1
9 8 1 NA NA
10 9 2 NA 1
11 10 1 NA NA