В группе R данные по видам спорта, в которых есть команды гостей и хозяев, - общее разочарование - PullRequest
0 голосов
/ 05 июня 2018

Я часто работаю со спортивными данными в R и сталкиваюсь с той же проблемой с dplyr :: group_by () при попытке вычислить итоговую статистику.У меня есть следующий фрейм данных с предсказанными очками в каждом матче группового этапа Кубка мира:

dput(worldcup.df)
structure(list(teamA_name = c("Russia", "Egypt", "Morocco", "Portugal", 
"France", "Argentina", "Peru", "Croatia", "Costa Rica", "Germany", 
"Brazil", "Sweden", "Belgium", "Tunisia", "Colombia", "Poland", 
"Russia", "Portugal", "Uruguay", "Iran", "Denmark", "France", 
"Argentina", "Brazil", "Nigeria", "Serbia", "Belgium", "Korea Republic", 
"Germany", "England", "Japan", "Poland", "Uruguay", "Saudi Arabia", 
"Iran", "Spain", "Denmark", "Australia", "Nigeria", "Iceland", 
"Mexico", "Korea Republic", "Serbia", "Switzerland", "Japan", 
"Senegal", "Panama", "England"), teamB_name = c("Saudi Arabia", 
"Uruguay", "Iran", "Spain", "Australia", "Iceland", "Denmark", 
"Nigeria", "Serbia", "Mexico", "Switzerland", "Korea Republic", 
"Panama", "England", "Japan", "Senegal", "Egypt", "Morocco", 
"Saudi Arabia", "Spain", "Australia", "Peru", "Croatia", "Costa Rica", 
"Iceland", "Switzerland", "Tunisia", "Mexico", "Sweden", "Panama", 
"Senegal", "Colombia", "Russia", "Egypt", "Portugal", "Morocco", 
"France", "Peru", "Argentina", "Croatia", "Sweden", "Germany", 
"Brazil", "Costa Rica", "Poland", "Colombia", "Tunisia", "Belgium"
), epA = c(1.64, 0.7051, 1.1294, 1.1116, 2.1962, 1.984, 1.5765, 
1.865, 1.2845, 2.0889, 2.1384, 1.5034, 2.1706, 0.5859, 2.1741, 
1.6272, 1.4941, 2.1482, 2.2089, 0.635, 1.7694, 1.6016, 1.7816, 
2.4745, 1.0762, 1.0326, 2.198, 1.0414, 2.2583, 2.198, 1.1264, 
1.0471, 1.9565, 1.2201, 0.8364, 2.3633, 0.9337, 0.7922, 0.5665, 
1.1593, 1.5544, 0.4698, 0.4331, 1.7843, 0.8872, 0.8157, 1.3932, 
1.3932), epB = c(1.094, 2.0809, 1.6016, 1.6204, 0.6098, 0.787, 
1.1535, 0.89, 1.4405, 0.6981, 0.6576, 1.2226, 0.6304, 2.2251, 
0.6279, 1.1058, 1.2319, 0.6488, 0.5991, 2.165, 0.9756, 1.1294, 
0.9644, 0.3895, 1.6588, 1.7064, 0.608, 1.6966, 0.5597, 0.608, 
1.6046, 1.6909, 0.8105, 1.5069, 1.9266, 0.4757, 1.8163, 1.9778, 
2.2495, 1.5697, 1.1746, 2.3712, 2.4179, 0.9617, 1.8688, 1.9503, 
1.3308, 1.3308)), .Names = c("teamA_name", "teamB_name", "epA", 
"epB"), class = "data.frame", row.names = c(NA, -48L))

head(worldcup.df)
  teamA_name   teamB_name    epA    epB
1     Russia Saudi Arabia 1.6400 1.0940
2      Egypt      Uruguay 0.7051 2.0809
3    Morocco         Iran 1.1294 1.6016
4   Portugal        Spain 1.1116 1.6204
5     France    Australia 2.1962 0.6098
6  Argentina      Iceland 1.9840 0.7870

Я рассчитал epA и epB как ожидаемые очки для команд A и B в каждой игре, и я 'Теперь я хотел бы сделать group_by (), чтобы вычислить общее количество ожидаемых очков каждой из 32 команд.Что я исторически делал, это что-то вроде этого:

asAgroupby = worldcup.df %>% 
  dplyr::group_by(teamA_name) %>%
  dplyr::summarise(totPts = sum(epA))

asBgroupby = worldcup.df %>% 
  dplyr::group_by(teamB_name) %>%
  dplyr::summarise(totPts = sum(epB))

outputdf = asAgroupby %>%
  dplyr::left_join(asBgroupby, by = c('teamA_name'='teamB_name')) %>%
  dplyr::mutate(totPts = totPts.x + totPts.y) %>%
  dplyr::select(-one_of(c('totPts.x', 'totPts.y')))

2 отдельных вызова group_by () для каждого из столбцов teamA и teamB, затем left_join, а затем суммирование столбцов и удаление лишнего столбца... тьфу.Это такой же простой случай, как и эта проблема: ровно 4 столбца (2 идентифицирующих столбца и 2 столбца статистики).Поскольку в тоннах спортивных данных есть столбцы для команд на выезде / выезд, это общая проблема.

Мне кажется, что мне нужен 1 кадр данных с 2-кратным числом строк и 1/2 столбцом, чтобы я мог сделать одну группу по.Спасибо за любую помощь, спасибо !!!

Редактировать: worldcup.df создается из длинных%>% функций dplyr - бонусных баллов, если это можно сделать без создания новых переменных, а просто:

worldcup.df %>%
  ... 

Ответы [ 4 ]

0 голосов
/ 05 июня 2018

Я тоже столкнулся с этой проблемой с некоторыми вещами из фэнтези-футбола.Вот как я обычно это делаю:

df %>% select(team = teamA_name, ep = epA) %>% 
     bind_rows(df %>% select(team = teamB_name, ep = epB)) %>% 
     group_by(team) %>% 
     summarize(ep = sum(ep))
0 голосов
/ 05 июня 2018

Вот рабочий процесс tidyverse, который работает путем переформатирования данных в длинный формат.Он отслеживает, кто находится в той же игре (game_id), и были ли они командой A или B - если это полезно.(Честно говоря, это та же основная идея, что и у @Emil, просто другой рабочий процесс для ее достижения.)

worldcup.long <- worldcup.df %>% 
  as_data_frame() %>%
  mutate(game_id = 1:n()) %>%
  gather(key, value, - game_id) %>%
  mutate(
    AB = str_extract(key, "A|B"),
    key = str_extract(key, "team|ep")
  ) %>%
  spread(key, value,convert = TRUE) 

outputdf <- worldcup.long %>%
  group_by(team) %>%
  summarize(totPts = sum(ep))
0 голосов
/ 05 июня 2018

Ваша интуиция верна: вам нужен фрейм данных с меньшим количеством столбцов и большим количеством строк.dplyr::gather сделает это;в этом случае вы можете сделать это в 2-х канальных gather вызовах.Первый gather создает строки из столбцов teamA_name и teamB_name.Вы можете по желанию извлечь A или B из записей в этом столбце, чтобы дать вам только «A» или «B» для каждой команды и ее результатов.Второй gather делает то же самое, но для столбцов epA и epB.Ключ для этого gather дает вам ту же информацию A или B, которую вы получили от a_or_b в предыдущем gather, поэтому я удалил этот дополнительный столбец (select(-pts_a_or_b)).

library(tidyverse)

df_long <- df %>%
  as_tibble() %>%
  gather(key = a_or_b, value = team, teamA_name, teamB_name) %>%
  mutate(a_or_b = str_extract(a_or_b, "(?<=team)\\w")) %>%
  gather(key = pts_a_or_b, value = points, epA, epB) %>%
  select(-pts_a_or_b)

df_long
#> # A tibble: 192 x 3
#>    a_or_b team       points
#>    <chr>  <chr>       <dbl>
#>  1 A      Russia      1.64 
#>  2 A      Egypt       0.705
#>  3 A      Morocco     1.13 
#>  4 A      Portugal    1.11 
#>  5 A      France      2.20 
#>  6 A      Argentina   1.98 
#>  7 A      Peru        1.58 
#>  8 A      Croatia     1.86 
#>  9 A      Costa Rica  1.28 
#> 10 A      Germany     2.09 
#> # ... with 182 more rows

Не стесняйтесь поправлять меня, если бы в сводном расчете было что-то большее, чем просто суммирование общих очков для каждой команды;если я понимаю, что вы ищете, вы можете получить это так:

df_long %>%
  group_by(team) %>%
  summarise(totPts = sum(points))
#> # A tibble: 32 x 2
#>    team       totPts
#>    <chr>       <dbl>
#>  1 Argentina    8.33
#>  2 Australia    8.32
#>  3 Belgium      8.33
#>  4 Brazil       8.51
#>  5 Colombia     8.31
#>  6 Costa Rica   8.33
#>  7 Croatia      8.23
#>  8 Denmark      8.22
#>  9 Egypt        8.24
#> 10 England      8.34
#> # ... with 22 more rows
0 голосов
/ 05 июня 2018

Вот решение с меньшим количеством строк и не требующее объединения:

df2 <- df[,c(2,1,4,3)]
names(df2) <- names(df)
rbind(df, df2) %>% group_by(teamA_name) %>% summarise(sum(epA))

# A tibble: 32 x 2
teamA_name `sum(epA)`
<chr>           <dbl>
 1 Argentina        6.02
 2 Australia        2.38
 3 Belgium          5.70
 4 Brazil           7.03
 5 Colombia         5.82
 6 Costa Rica       2.64
 7 Croatia          4.40
 8 Denmark          3.86
 9 Egypt            3.44
10 England          5.82

То же, что и у OP:

outputdf
# A tibble: 32 x 2
teamA_name `sum(epA)`
<chr>           <dbl>
 1 Argentina        6.02
 2 Australia        2.38
 3 Belgium          5.70
 4 Brazil           7.03
 5 Colombia         5.82
 6 Costa Rica       2.64
 7 Croatia          4.40
 8 Denmark          3.86
 9 Egypt            3.44
10 England          5.82
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...