#r
#r #агрегировать #plyr #переформирование2
Вопрос:
Я пытаюсь получить подсчеты каждой комбинации уровней двух переменных: «неделя» и «идентификатор». Я бы хотел, чтобы результат имел «id» в виде строк и «week» в виде столбцов, а подсчеты — в качестве значений.
Пример того, что я пробовал до сих пор (пробовал кучу других вещей, включая добавление фиктивной переменной = 1, а затем fun.aggregate = sum
поверх этого):
library(plyr)
ddply(data, .(id), dcast, id ~ week, value_var = "id",
fun.aggregate = length, fill = 0, .parallel = TRUE)
Однако я, должно быть, делаю что-то не так, потому что эта функция не завершается. Есть ли лучший способ сделать это?
Ввод:
id week
1 1
1 2
1 3
1 1
2 3
Вывод:
1 2 3
1 2 1 1
2 0 0 1
Ответ №1:
Вы могли бы просто использовать table
команду:
table(data$id,data$week)
1 2 3
1 2 1 1
2 0 0 1
Если «id» и «неделя» являются единственными столбцами в вашем фрейме данных, вы можете просто использовать:
table(data)
# week
# id 1 2 3
# 1 2 1 1
# 2 0 0 1
Комментарии:
1. 1 взрыв. У вас есть умение заставлять мои решения выглядеть совершенно многословными, окольными и пешеходными.
2. Если у вас много данных и операций, которые нельзя так сильно упростить, вам может помочь пакет ‘data.table’.
Ответ №2:
Вам это не нужно ddply
. Достаточно dcast
from reshape2
:
dat <- data.frame(
id = c(rep(1, 4), 2),
week = c(1:3, 1, 3)
)
library(reshape2)
dcast(dat, id~week, fun.aggregate=length)
id 1 2 3
1 1 2 1 1
2 2 0 0 1
Редактировать: для базового решения R (кроме table
— как опубликовано Джошуа Ульрихом), попробуйте xtabs
:
xtabs(~id week, data=dat)
week
id 1 2 3
1 2 1 1
2 0 0 1
Ответ №3:
Причина ddply
, по которой это занимает так много времени, заключается в том, что разделение по группам не выполняется параллельно (только вычисления по «разделениям»), поэтому при большом количестве групп это будет медленно (и .parallel = T
) не поможет.
Подход, использующий data.table::dcast
( data.table
версия> = 1.9.2), должен быть чрезвычайно эффективным по времени и памяти. В этом случае мы можем полагаться на значения аргументов по умолчанию и просто использовать:
library(data.table)
dcast(setDT(data), id ~ week)
# Using 'week' as value column. Use 'value.var' to override
# Aggregate function missing, defaulting to 'length'
# id 1 2 3
# 1: 1 2 1 1
# 2: 2 0 0 1
Или установка аргументов явно:
dcast(setDT(data), id ~ week, value.var = "week", fun = length)
# id 1 2 3
# 1: 1 2 1 1
# 2: 2 0 0 1
data.table
Альтернативы, существовавшие до версии 1.9.2, см. в разделе Изменения.
Ответ №4:
Одним tidyverse
из вариантов может быть :
library(dplyr)
library(tidyr)
df %>%
count(id, week) %>%
pivot_wider(names_from = week, values_from = n, values_fill = list(n = 0))
#spread(week, n, fill = 0) #In older version of tidyr
# id `1` `2` `3`
# <dbl> <dbl> <dbl> <dbl>
#1 1 2 1 1
#2 2 0 0 1
Используя только pivot_wider
—
tidyr::pivot_wider(df, names_from = week,
values_from = week, values_fn = length, values_fill = 0)
Или использование tabyl
из janitor
:
janitor::tabyl(df, id, week)
# id 1 2 3
# 1 2 1 1
# 2 0 0 1
данные
df <- structure(list(id = c(1L, 1L, 1L, 1L, 2L), week = c(1L, 2L, 3L,
1L, 3L)), class = "data.frame", row.names = c(NA, -5L))