Агрегируйте фрейм данных, сохраняя другие переменные, с помощью dplyr - PullRequest
0 голосов
/ 08 мая 2018

Предположим, у меня есть следующий фрейм данных (обратите внимание на длину 'показателя'):

id = 1:10^8
school = LETTERS[1:10]
class = paste0(school, rep(1:10, each=10))
score = rnorm(10^8)

df = data.frame(id, school, class, score,
                stringsAsFactors = FALSE) 

Я хочу вычислить среднее значение для каждого из 100 классов. Еще я тоже хочу сохранить переменную школы в результатах. Использование dplyr:

df %>% group_by(class) %>% 
  summarise(mean = mean(score),
            school = unique(school))

Это работает, но медленно (8 секунд на моей машине, и мои данные на самом деле намного больше). Я думаю, что одним из вариантов может быть не использование unique (), а член семьи join (). Но мне нужно сначала определить другой df следующим образом:

df_join = data.frame(class, school,
                     stringsAsFactors = FALSE)

, а затем:

df %>% group_by(class) %>% 
    summarise(mean = mean(score)) %>% 
    left_join(df_join)

Это работает и менее медленно, так как теперь это занимает 6 секунд. Тем не менее, создать здесь df_join было легко, потому что я изобрел кадр данных, но в реальной жизни получение df_join может быть намного сложнее. Поэтому я хотел бы использовать только исходный фрейм данных (df).

Есть идеи, как сделать это проще (и, возможно, быстрее) с помощью dplyr? (Я там проверял, но не нашел решения: Агрегирование по уровням факторов, сохранение других переменных в результирующем фрейме данных )

1 Ответ

0 голосов
/ 08 мая 2018

Поскольку у вас есть только одна уникальная школа на класс, вы можете просто включить школьную переменную в переменные группировки:

df %>% group_by(school, class) %>% summarize(mean_score = mean(score))
# # A tibble: 100 x 3
# # Groups:   school [?]
# school class mean_score
# <chr>  <chr>      <dbl>
# 1 A      A1      0.000506
# 2 A      A10    -0.000275
# 3 A      A2      0.00136 
# 4 A      A3      0.000405
# 5 A      A4     -0.00156 
# 6 A      A5     -0.00214 
# 7 A      A6     -0.00108 
# 8 A      A7     -0.000534
# 9 A      A8      0.000804
# 10 A      A9      0.00106 
# # ... with 90 more rows

Вот эквивалент data.table:

library(data.table)
setDT(df, key = c("school", "class"))
df[, .(mean_score = mean(score)), by=.(school, class)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...