R语言循环中使用mutate与case_when匹配帆船比赛编号异常问题
问题原因
你现有代码的核心问题是:每次循环执行mutate(Racenum = ...)时,都会直接重写整个Racenum列,仅当前循环对应比赛的时间区间内的行赋值为对应场次编号,其余行全部默认设为NA,前面循环生成的匹配结果会被后续循环完全覆盖,最终只能保留最后一个比赛的匹配结果。
修复方案
方案1:修改原有循环逻辑
先初始化Racenum列为空,循环时仅修改符合条件的行,不覆盖已有匹配结果:
library(dplyr) # 先初始化比赛编号列为NA lg$RaceNum <- NA_character_ for (i in RaceInfo$RaceNum) { # 取出当前比赛的起止时间 cur_start <- RaceInfo$RaceStartTime[RaceInfo$RaceNum == i] cur_end <- RaceInfo$RaceFinishTime[RaceInfo$RaceNum == i] # 仅修改符合时间条件的行 lg$RaceNum[lg$Time >= cur_start & lg$Time <= cur_end] <- i }
方案2:非等值连接(更高效,推荐)
R中处理区间匹配更推荐用非等值连接实现,无需循环,大数据量下性能远高于循环:
library(dplyr) lg <- lg %>% # 先和比赛信息表匹配符合时间区间的记录 left_join(RaceInfo, by = join_by(between(Time, RaceStartTime, RaceFinishTime))) %>% # 保留原数据所有列,仅保留新增的比赛编号字段 select(all_of(colnames(lg)), RaceNum)
注意:如果是dplyr 1.1.0以下版本,不支持
join_by语法,可以用以下写法:lg <- lg %>% rowwise() %>% mutate(RaceNum = RaceInfo$RaceNum[between(Time, RaceInfo$RaceStartTime, RaceInfo$RaceFinishTime)][1]) %>% ungroup()
注意事项
- 需确保
lg$Time和RaceInfo中的起止时间字段时区完全一致,否则会出现匹配偏差 - 如果存在单条航行数据同时落在多个比赛时间区间的情况,建议先对
RaceInfo表做时间区间重叠校验,避免匹配冲突
内容的提问来源于stack exchange,提问作者TDaw
相关产品推荐
相关产品推荐

