求助:在R语言中计算对战双方历史胜场次数(附数据集)
我来帮你解决这个历史对战统计的问题!针对你15000行的数据集,我准备了两种高效的R实现方案,既能保证准确性,也能应对较大的数据量:
首先确认你的示例数据
day <- c(1,2,3,4,5,6,7,8) id1 <- c(100,200,100,400,200,200,300,200) id2 <- c(200,400,200,300,400,100,400,100) result<-c(1,0,1,0,1,0,0,1) tables <- data.frame(day,id1,id2,result)
方案1:使用dplyr(推荐,代码更清晰易维护)
dplyr的分组和窗口函数能让我们很直观地处理逐行历史统计:
library(dplyr) tables_processed <- tables %>% # 先按day排序,确保按时间顺序统计历史 arrange(day) %>% # 生成标准化对战组合:把每对id按从小到大排序后拼接,保证同一对战组统一归类 mutate(pair = paste(pmin(id1, id2), pmax(id1, id2), sep = "-")) %>% # 按标准化对战组合分组 group_by(pair) %>% mutate( # 标记当前行的id1是标准化组合中的第一个还是第二个元素 id1_is_first = id1 == pmin(id1, id2), # 转换结果:对标准化组合来说,first_win=1表示第一个id赢,0表示第二个id赢 first_win = ifelse(id1_is_first, result, 1 - result), # 计算HTH1:当前行之前,id1战胜id2的次数 HTH1 = ifelse( id1_is_first, lag(cumsum(first_win), default = 0), # id1是第一个元素,取之前first_win的累计 lag(cumsum(1 - first_win), default = 0) # id1是第二个元素,取之前second_win的累计 ), # 计算HTH2:当前行之前,id2战胜id1的次数,逻辑与HTH1相反 HTH2 = ifelse( id1_is_first, lag(cumsum(1 - first_win), default = 0), lag(cumsum(first_win), default = 0) ) ) %>% ungroup() %>% # 移除临时辅助列 select(-pair, -id1_is_first, -first_win) # 查看结果 print(tables_processed)
方案2:Base R实现(无需加载额外包)
如果你不想依赖dplyr,用Base R也能实现同样的逻辑:
# 先按day排序数据,保证时间顺序正确 tables <- tables[order(tables$day), ] # 创建标准化对战组合列 tables$pair <- apply(tables[, c("id1", "id2")], 1, function(x) paste(sort(x), collapse = "-")) # 标记当前id1是否是标准化组合中的第一个元素 tables$id1_is_first <- mapply(function(a, b) a == min(a, b), tables$id1, tables$id2) # 转换结果为标准化组合的胜负标记 tables$first_win <- ifelse(tables$id1_is_first, tables$result, 1 - tables$result) # 按对战组合分组计算累计胜负次数 tables$cum_first_win <- ave(tables$first_win, tables$pair, FUN = cumsum) tables$cum_second_win <- ave(1 - tables$first_win, tables$pair, FUN = cumsum) # 计算HTH1和HTH2:取当前行之前的累计值(用c(0, head(...))实现lag效果) tables$HTH1 <- ifelse( tables$id1_is_first, c(0, head(tables$cum_first_win, -1)), c(0, head(tables$cum_second_win, -1)) ) tables$HTH2 <- ifelse( tables$id1_is_first, c(0, head(tables$cum_second_win, -1)), c(0, head(tables$cum_first_win, -1)) ) # 移除临时辅助列 tables <- tables[, !names(tables) %in% c("pair", "id1_is_first", "first_win", "cum_first_win", "cum_second_win")] # 查看结果 print(tables)
关键逻辑解释
两种方案的核心思路是一致的:
- 标准化对战组合:把每一对对战的id按固定顺序(比如从小到大)拼接,这样不管
id1和id2的顺序如何,同一组对战都会被归为同一个分组,避免重复统计。 - 映射历史胜负:根据当前行
id1在标准化组合中的位置,把历史胜负结果映射到id1和id2的关系上,确保统计的是当前行之前的对战次数(用lag或head排除当前行的结果)。
运行任意一种方案后,你都会得到和期望完全一致的HTH1和HTH2列,而且针对15000行的数据,两种方案的效率都足够应对。
内容的提问来源于stack exchange,提问作者Mirko Piccolo
相关产品推荐
相关产品推荐

