首页 > 解决方案 > R:按 2 列分组,但仅当第 2 列不匹配时

问题描述

我是 R(和 dplyr)的新手,我目前正在处理一些季节性足球数据,需要一些帮助。目前,如果一名球员转会到同一联赛中的另一家具乐部,那么数据行和所有指标都会简单地重复,但会使用新的 team_id。但是,如果球员转会到另一个联赛,那么指标就会分开。

为了一致性起见,我需要解决这个问题,这意味着我必须:

按 comp_id 不匹配的 player_id 分组

(足球规则规定您一个赛季最多只能为 2 家具乐部效力,因此这消除了进一步的复杂性,因此这个简单的规则可以解决所有问题)

所以换句话说,如果有重复的所有行求和,但前提是 comp_id 不同

我试图在 dplyr 中执行此操作,并希望有某种方式可以编写此代码,例如:

football_data %>%
group_by(player_id, !comp_id)

但这不起作用,而且完全正确。

我的另一个选择是基于复合键(player_id,comp_id)和 group_by player_id 创建一个附加列,仅在复合键计数 = 1 的情况下,但即便如此,我仍在努力用 dplyr 编写它。

任何建议都会非常受欢迎。

编辑:

有接近一百个指标,所以我将按以下方式进行简化:

player_id   player_name   comp,   team,  metric1, metric2, metric3 .....
1            Lacazette     Bund   Dort     20       30       20
1            Lacazette     EPL    Ars      10       15       15
2            Arnautovic    EPL    Stoke    30       40       30     
2            Arnautovic    EPL    W. Ham   30       40       30       

所以在这个例子中,当球员移动联赛(Lacazette)时数据指标被拆分,但如果转会在同一个联赛(Arnautovic)则不会。

因此,为了保持一致性,我需要对第一个玩家而不是第二个玩家的指标求和

导致输出:

player_id   player_name   comp,   team,  metric1, metric2, metric3 .....
1            Lacazette     Bund   Dort     30       45       35
1            Lacazette     EPL    Ars      30       45       35
2            Arnautovic    EPL    Stoke    30       40       30     
2            Arnautovic    EPL    W. Ham   30       40       30     

标签: rgroup-bydplyr

解决方案


本质上,你想要

  1. 获取变量的玩家级别sum,分组为metriccomp
  2. join他们回到完整的数据框。


library(tidyverse)
#> -- Attaching packages ----------------------------------------------------------------------------------------------------- tidyverse 1.2.1 --
#> v ggplot2 2.2.1     v purrr   0.2.4
#> v tibble  1.4.1     v dplyr   0.7.4
#> v tidyr   0.7.2     v stringr 1.2.0
#> v readr   1.1.1     v forcats 0.2.0
#> -- Conflicts -------------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
#> x dplyr::filter() masks stats::filter()
#> x dplyr::lag()    masks stats::lag()

df <- data.frame(player_id = c(1, 1, 2, 2), 
                 player_name = c("Lacazette", "Lacazette", "Arnuatovic", "Arnuatovic"), 
                 comp = c("Bund", "EPL", "EPL", "EPL"), 
                 team = c("Dort", "Ars", "Stoke", "W. Ham"), 
                 metric1 = c(20, 10, 30, 30), 
                 metric2 = c(30, 15, 40, 40), 
                 metric3 = c(20, 15, 30, 30))

df %>% 
  distinct(player_id, player_name, comp, .keep_all = T) %>% 
  group_by(player_id) %>% 
  summarize_at(vars(metric1:metric3), funs(sum)) %>% 
  left_join(df %>% select(player_id:team), ., by = "player_id")


#>   player_id player_name comp   team metric1 metric2 metric3
#> 1         1   Lacazette Bund   Dort      30      45      35
#> 2         1   Lacazette  EPL    Ars      30      45      35
#> 3         2  Arnuatovic  EPL  Stoke      30      40      30
#> 4         2  Arnuatovic  EPL W. Ham      30      40      30

推荐阅读