【问题标题】:R function to summarize multiple columns of data with multiple functions, grouped by a columnR函数用多个函数汇总多列数据,按列分组
【发布时间】:2018-10-26 19:01:50
【问题描述】:

我有一个包含以下列的数据框:

  • game_id - chr,每场比赛 1 个 ID,每场比赛多行
  • home_lineup - chr
  • away_lineup - chr
  • home_plusminus - 整数
  • away_plusminus - 整数
  • home_team - chr
  • away_team - chr

我需要为每个 home_lineup 和每个 away_lineup 计算每场比赛的 home_plusminus 和 away_plusminus 之和。

数据如下:

game_id home_lineup awaylineup home_Plusminus Away_Plusminus home_team  away_team
12345   L1          L2          -2              2            BOS         ATL
12345   L3          L4           3             -3            BOS         ATL
12345   L3          L4           3             -3            BOS         ATL
45678   L2          L1           3             -3            ATL         BOS
45678   L2          L7           1             -1            ATL         BOS
45678   L8          L1           3             -3            ATL         BOS

以上数据显示了 2 场比赛。

我希望最终输出如下所示:

Team Lineup PlusMinus Pergame
BOS  L1     -8        -4.0
BOS  L3      6         6.0
BOS  L7     -1        -1.0
ATL  L2      6         3.0
ATL  L4     -6        -6.0
ATL  L8      3         3.0

所以在上面的例子中,L1 参加了两场比赛,总共加减 -8。 L3 只打了一场比赛。

【问题讨论】:

  • 在您的示例数据中,相同的行 2+3 是什么意思?在您的输出中,这两行似乎都计算了 ATL L4,但 BOS L3 只计算了一次。能否请您解释或修改?
  • 每一行代表一场篮球比赛。所以在第 2 行和第 3 行中,同一组玩家在同一场比赛中的 2 次不同比​​赛中得分相同。我修复了 BOS L3 的输出(谢谢!)
  • 以下是实施 Jon 解决方案的完整功能:gist.github.com/yarnedia/89da12774cf888d6ca1c77f9a0c4d748

标签: r summarization


【解决方案1】:

这是tidyrdplyr 的一种方法。

library(tidyr); library(dplyr)

# Step 1 - make into tidy data frame with one row per observation
home <- df %>% select(game_id, contains("home")) %>% 
  rename("Lineup" = "home_lineup", "Team" = "home_team", "plusminus" = "home_Plusminus")

away <- df %>% select(game_id, contains("away")) %>% 
  rename("Lineup" = "awaylineup", "Team" = "away_team", "plusminus" = "Away_Plusminus")

tidy <- bind_rows(home, away, .id = "location")



# Step 2 - summarize
output <- tidy %>%
  group_by(Team, Lineup) %>%
  summarize(PlusMinus = sum(plusminus),
            PerGame = PlusMinus/n_distinct(game_id)) %>% ungroup()

输出:

> output
# A tibble: 6 x 4
  Team  Lineup PlusMinus PerGame
  <chr> <chr>      <int>   <dbl>
1 ATL   L2             6       3
2 ATL   L4            -6      -6
3 ATL   L8             3       3
4 BOS   L1            -8      -4
5 BOS   L3             6       6
6 BOS   L7            -1      -1

样本数据:

df <- read.table(header = T, stringsAsFactors = F, text = "
                 game_id home_lineup awaylineup  home_Plusminus  Away_Plusminus  home_team   away_team
 12345  L1          L2          -2              2               BOS       ATL
     12345  L3          L4           3             -3               BOS       ATL
     12345  L3          L4           3             -3               BOS       ATL
     45678  L2          L1           3             -3               ATL       BOS
     45678  L2          L7           1             -1               ATL       BOS
     45678  L8          L1           3             -3               ATL       BOS")

【讨论】:

  • 这看起来非常接近,但有一个问题...波士顿 L1 输出除以 3(行数)而不是 2(游戏数)。 L1 在第 45678 场比赛中有 2 场比赛,在第 12345 场比赛中有 1 场比赛。所以每场比赛应该是 4 场。
  • 你成功了。非常感谢!我是 R 新手,看到工作代码有很大帮助。
【解决方案2】:

Jon 的类似解决方案:

library(tidyverse)

dat <- tribble(
  ~game_id, ~home_lineup, ~awaylineup,  ~home_Plusminus,  ~Away_Plusminus,  ~home_team,   ~away_team,
  12345,  "L1",          "L2",          -2,              2,               "BOS",       "ATL",
  12345,  "L3",          "L4",           3,             -3,               "BOS",       "ATL",
  # 12345,  "L3",          "L4",           3,             -3,               "BOS",       "ATL",
  45678,  "L2",          "L1",           3,             -3,               "ATL",       "BOS",
  45678,  "L2",          "L7",           1,             -1,               "ATL",       "BOS",
  45678,  "L8",          "L1",           3,             -3,               "ATL",       "BOS"
)

long <- 
  dat %>% 
  gather(where, team, home_team:away_team) %>% 
  mutate(
    home_lineup = case_when(where == "home_team" ~ home_lineup,
                            TRUE ~ NA_character_),
    away_lineup = case_when(where == "away_team" ~ awaylineup,
                            TRUE ~ NA_character_),
    home_plusminus = case_when(where == "home_team" ~ home_Plusminus,
                            TRUE ~ NA_real_),
    away_plusminus = case_when(where == "away_team" ~ Away_Plusminus,
                            TRUE ~ NA_real_)
  ) %>% 
  select(-home_Plusminus, -Away_Plusminus, -awaylineup) %>% 
  gather(plus_minus_type, plus_minus, home_plusminus:away_plusminus) %>%
  gather(lineup_type, lineup, home_lineup:away_lineup, -where, -team) %>% 
  mutate(
    where = where %>% str_remove("_team"),
    lineup_type = lineup_type %>% str_remove("_") %>% str_remove("lineup"),
    plus_minus_type = lineup_type %>% str_remove("_Plusminus")
  ) %>% 
  drop_na()

long %>% 
  group_by(
    team, lineup
  ) %>% 
  summarise(
    PlusMinus = sum(plus_minus),
    Pergame = sum(plus_minus) / n()
  )
#> # A tibble: 6 x 4
#> # Groups:   team [?]
#>   team  lineup PlusMinus Pergame
#>   <chr> <chr>      <dbl>   <dbl>
#> 1 ATL   L2             6    2   
#> 2 ATL   L4            -3   -3   
#> 3 ATL   L8             3    3   
#> 4 BOS   L1            -8   -2.67
#> 5 BOS   L3             3    3   
#> 6 BOS   L7            -1   -1

reprex package (v0.2.1) 于 2018 年 10 月 26 日创建

【讨论】:

  • 感谢您的帮助,阿曼达。我成功实施了 Jon 的解决方案,但看看你们俩是如何解决这个问题的非常有帮助。
猜你喜欢
  • 1970-01-01
  • 2017-06-24
  • 2021-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 2021-04-14
  • 2020-09-16
相关资源
最近更新 更多