R Sports dataframe – объединение и агрегирование данных в нескольких столбцах

У меня есть фрейм данных R со спортивными данными, например:

 HomeTeam   AwayTeam   HomeWin     Draw     AwayWin
1 Barcelona    Madrid    2.30      3.28       3.27
2    Madrid Liverpool    8.79      5.12       1.36
3 Liverpool Barcelona    3.41      3.34       2.21
4    Madrid Barcelona    1.38      5.08       7.92
5 Liverpool    Madrid    1.53      4.07       6.83
6 Barcelona Liverpool    3.35      3.62       2.12

Итак, отдельные столбцы для команд хозяев и гостей, а затем 3 столбца для шансов на победу хозяев, ничьей и гостей.

Я хочу создать новый фрейм данных, показывающий средние шансы на победу для каждой из команд. Итак, я хочу взять коэффициенты на победу (независимо от того, дома они или на выезде) для каждой команды и вычислить среднее значение. Например, в случае с «Барселоной» средние шансы на победу составляют (2,30 + 2,21 + 7,92 + 3,35) / 4 = 3,95. Таблица, которую я хочу сделать, выглядит так:

      Team       AverageWinOdds
1   Barcelona           3.95
2    Madrid             5.07
3   Liverpool           2.11

Как я могу это сделать?


3
62
3

Ответы:

В базе мы можем сделать

(1)

# X := your data 
list(X[c("HomeTeam", "HomeWin")], X[c("AwayTeam", "AwayWin")]) |>
  lapply(setNames, c("Team", "Win")) |> 
  do.call(what = "rbind") |>
  aggregate(cbind(AvgWinOdds = Win)~Team, data = _, mean)

или (2)

(с использованием unlist()-подхода @ThomasIsCoding)

aggregate(list(AvgWinOdds = unlist(X[grep("Win", n<-colnames(X))])), 
          list(Team = unlist(X[grep("Team", n)])), 
          mean)

или (3)

используя несколько громоздкую функцию reshape, предложенную @thelatemail

reshape(X, 
        varying = list(c("HomeTeam","AwayTeam"), c("HomeWin","AwayWin")), 
        v.names = c("Team","Win"), 
        direction = "long") |> 
  aggregate(cbind(AvgWin = Win)~Team, data = _, FUN = mean)

предоставление

       Team AvgWinOdds
1 Barcelona     3.9450
2 Liverpool     2.1050
3    Madrid     5.0675

(где порядок отличается от подхода к подходу).


Вы можете попробовать

library(dplyr)

df %>%
  {
    bind_cols(
      Team = unlist(select(., ends_with("Team"))),
      AvgWinOdds = unlist(select(., ends_with("Win"))),
    )
  } %>%
  summarise(AvgWinOdds = mean(AvgWinOdds), .by = Team)

что дает

# A tibble: 3 × 2
  Team      AvgWinOdds
  <chr>          <dbl>
1 Barcelona       3.94
2 Madrid          5.07
3 Liverpool       2.10

данные

> dput(df)
structure(list(HomeTeam = c("Barcelona", "Madrid", "Liverpool",
"Madrid", "Liverpool", "Barcelona"), AwayTeam = c("Madrid", "Liverpool", 
"Barcelona", "Barcelona", "Madrid", "Liverpool"), HomeWin = c(2.3,
8.79, 3.41, 1.38, 1.53, 3.35), Draw = c(3.28, 5.12, 3.34, 5.08,
4.07, 3.62), AwayWin = c(3.27, 1.36, 2.21, 7.92, 6.83, 2.12)), class = "data.frame", row.names = c("1",
"2", "3", "4", "5", "6"))

Решено

1) Используя данные, воспроизводимые в примечании в конце, используйте reframe, чтобы создать фрейм данных с двумя столбцами, а затем summarize его.

library(dplyr)

dat %>%
  reframe(Team = c(HomeTeam, AwayTeam), Win = c(HomeWin, AwayWin)) %>%
  summarize(avgWin = mean(Win), .by = Team)
##        Team avgWin
## 1 Barcelona 3.9450
## 2    Madrid 5.0675
## 3 Liverpool 2.1050

2) Альтернативой является использование pivot_longer для создания длинного фрейма данных, а затем summarize, как и раньше.

library(dplyr)
library(tidyr)

dat %>%
  pivot_longer(cols = 1:2, values_to = "Team") %>%
  mutate(Win = ifelse(name == "HomeTeam", HomeWin, AwayWin)) %>%
  summarize(avgWin = mean(Win), .by = Team)
## # A tibble: 3 × 2
##   Team      avgWin
##   <chr>      <dbl>
## 1 Barcelona   3.94
## 2 Madrid      5.07
## 3 Liverpool   2.10

Примечание

Входные данные в легко воспроизводимой форме:

dat <- data.frame(
  HomeTeam = c("Barcelona", "Madrid", "Liverpool", "Madrid", "Liverpool", "Barcelona"),
  AwayTeam = c("Madrid", "Liverpool", "Barcelona", "Barcelona", "Madrid", "Liverpool"),
  HomeWin = c(2.3, 8.79, 3.41, 1.38, 1.53, 3.35),
  Draw = c(3.28, 5.12, 3.34, 5.08, 4.07, 3.62),
  AwayWin = c(3.27, 1.36, 2.21, 7.92, 6.83, 2.12)
)