r - 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
解决方案
本质上,你想要
- 获取变量的玩家级别
sum
,分组为metric
comp
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