У меня есть фрейм данных 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
Как я могу это сделать?
В базе мы можем сделать
(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)
)
Вы также можете
reshape
использовать длинный формат из двух столбцов, а затем агрегировать -reshape(dat, varying=list(c("HomeTeam","AwayTeam"), c("HomeWin","AwayWin")), v.names=c("Team","Win"), direction = "long") |> aggregate(cbind(AvgWin = Win) ~ Team, data=_, FUN=mean)