Можно ли объединить суммирование с summarise_at в одном group_by с dplyr - PullRequest
0 голосов
/ 17 января 2019

Редактировать: только что понял, что столбец side в данных вообще не используется, поэтому, пожалуйста, не учитывайте его для целей примера.

У меня есть большой фрейм данных баскетбольных игр в режиме игры за игрой, и я хотел бы выполнить group_by, summarise и summarise_at для моих данных. Ниже приведено подмножество моего фрейма данных:

> dput(zed)
structure(list(side = c("right", "right", "right", "right", "right", 
"right", "left", "right", "right", "right", "left", "right", 
"left", "left", "left", "right", "right", "right", "left", "right"
), result = c("twopointmiss", "twopointmade", "twopointmade", 
"twopointmiss", "twopointmade", "twopointmade", "twopointmiss", 
"twopointmade", "twopointmade", "twopointmade", "twopointmade", 
"twopointmade", "twopointmiss", "twopointmiss", "twopointmiss", 
"twopointmiss", "twopointmade", "twopointmade", "twopointmiss", 
"twopointmiss"), zonenumber = c(1, 1, 1, 1, 2, 3, 2, 3, 2, 3, 
4, 4, 4, 1, 1, 2, 3, 2, 3, 4), team = c("Bos", "Bos", "Bos", 
"Bos", "Bos", "Bos", "Bos", "Bos", "Bos", "Bos", "Min", "Min", 
"Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min")), row.names = c(3L, 
5L, 8L, 14L, 17L, 23L, 28L, 30L, 39L, 41L, 42L, 43L, 47L, 52L, 
54L, 58L, 60L, 63L, 69L, 72L), class = "data.frame")

>   zed
    side       result zonenumber team
3  right twopointmiss          1  Bos
5  right twopointmade          1  Bos
8  right twopointmade          1  Bos
14 right twopointmiss          1  Bos
17 right twopointmade          2  Bos
23 right twopointmade          3  Bos
28  left twopointmiss          2  Bos
30 right twopointmade          3  Bos
39 right twopointmade          2  Bos
41 right twopointmade          3  Bos
42  left twopointmade          4  Min
43 right twopointmade          4  Min
47  left twopointmiss          4  Min
52  left twopointmiss          1  Min
54  left twopointmiss          1  Min
58 right twopointmiss          2  Min
60 right twopointmade          3  Min
63 right twopointmade          2  Min
69  left twopointmiss          3  Min
72 right twopointmiss          4  Min

В приведенном ниже примере я только использует summarise, так как в настоящее время я не уверен, как использовать summarise и summarise_at с тем же group_by по телефону:

>   grouped.df <- zed %>%
+     dplyr::group_by(team) %>%
+     dplyr::summarise(
+       shotsMade = sum(result == "twopointmade"),
+       shotsAtt = n(),
+       shotsPct = round(shotsMade / shotsAtt),
+       points = 2 * shotsMade,
+       
+       z1Made = sum(zonenumber == 1),
+       z2Made = sum(zonenumber == 2),
+       z3Made = sum(zonenumber == 3),
+       z4Made = sum(zonenumber == 4)
+     )
>   grouped.df
# A tibble: 2 x 9
  team  shotsMade shotsAtt shotsPct points z1Made z2Made z3Made z4Made
  <chr>     <int>    <int>    <dbl>  <dbl>  <int>  <int>  <int>  <int>
1 Bos           7       10        1     14      4      3      3      0
2 Min           4       10        0      8      2      2      2      4

В приведенном ниже примере я хотел бы создать первые 4 столбца (shotsMade, shotsAtt, shotsPct, points) в summarise и создать столбцы z#made с summarise_at. В моих полных данных есть ~ 30 уникальных столбцов, которые я планирую создать с помощью summarise, и ~ 80 похожих столбцов, которые я планирую создать с помощью summarise_at.

Ради небольшого примера я не хотел приводить весь свой фрейм данных для этого примера. Если я смогу реализовать оба summarise и summarise_at в приведенном выше примере, то я смогу сделать это и для моего полного фрейма данных.

Любые мысли по этому поводу приветствуются, поскольку я особенно заинтересован в улучшении с помощью функций _at в dplyr. Спасибо!

1 Ответ

0 голосов
/ 17 января 2019

Я не думаю, что есть способ действительно использовать и summarise, и summarise_at, так как ясно, что мы не сможем выполнить второй после потери многих строк и столбцов.

Итак, вместо этого мы можем использовать mutate, mutate_at, а затем отбрасывать определенные строки (и, возможно, столбцы). Разница между этим и каким-то магическим применением summarise и summarise_at будет заключаться в том, что первый подход не будет сбрасывать какие-либо переменные. Я думаю, это зависит от того, хорошо ли это для вас. Ниже я добавляю дополнительную строку select(-one_of(setdiff(names(zed), "team"))), которая на самом деле удалит все столбцы, которые будут отбрасываться суммирующим списком.

zed$zonenumber2 <- zed$zonenumber # Example
zed %>%
  group_by(team) %>%
  mutate(
    shotsMade = sum(result == "twopointmade"),
    shotsAtt = n(),
    shotsPct = round(shotsMade / shotsAtt),
    points = 2 * shotsMade) %>%
  mutate_at(
    vars(contains("zone")), 
    .funs = funs(Made1 = sum(. == 1), Made2 = sum(. == 2),
                 Made3 = sum(. == 3), Made4 = sum(. == 4))) %>%
  filter(!duplicated(team)) %>%
  select(-one_of(setdiff(names(zed), "team"))) # May want to remove
# A tibble: 2 x 13
# Groups:   team [2]
#   team  shotsMade shotsAtt shotsPct points zonenumber_Made1 zonenumber2_Mad… zonenumber_Made2
#   <chr>     <int>    <int>    <dbl>  <dbl>            <int>            <int>            <int>
# 1 Bos           7       10        1     14                4                4                3
# 2 Min           4       10        0      8                2                2                2
# … with 5 more variables: zonenumber2_Made2 <int>, zonenumber_Made3 <int>,
#   zonenumber2_Made3 <int>, zonenumber_Made4 <int>, zonenumber2_Made4 <int>
...