#r #tidyverse #summarize
Вопрос:
У меня есть фрейм данных, содержащий данные, которые выглядят примерно так:
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")
)
Я хочу суммировать количество ответов » да » / » нет » в переменных one
two
, и three
которые обычно я бы использовал df %>% group_by(group1,group2,one) %>% summarise(n())
. Есть ли какой-либо способ суммировать все три столбца, а затем связать их все в один выходной файл df без необходимости вручную выполнять код над каждым столбцом? Я пробовал использовать цикл for, но не могу group_by()
распознать имя colname, которое я даю в качестве входных данных
Комментарии:
1. Принял ответ
Ответ №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
Создано 2021-05-12 пакетом reprex (v2.0.0)
Комментарии:
1. Причина в том, что это
==
преобразование его в логический вектор. Проверятьdf %>% group_by(group1, group2) %>% summarise(new = list(c_across(everything()) == "yes")) %>% pull(new)
2.т. е. когда вы делаете
c_across
, он возвращаетvector
df %>% group_by(group1, group2) %>% summarise(new = list(c_across(everything()))) -> out
проверку «Сейчасout
» иdf
«иout$new
«. Сrowwise
, существует ограничение, что он сгруппирован по строкам. Но здесь этого ограничения нет. Таким образом, он раскрывается в обычном столбце для каждой группы3.Также вы могли бы использовать
table
сunnest_wider
df %>% group_by(group1, group2) %>% summarise(count = list(table(c_across(everything()))), .groups = 'drop') %>% unnest_wider(count)
4. Спасибо @akrun за объяснение. Понял.
Ответ №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
помощью , мы можем использовать by
и table
by(df[3:5], df[1:2], function(x) table(unlist(x)))