如何用循环替换data.frame中每周非NA行的班次值(每周不重复)
解决R语言班次替换问题的思路与代码
核心思路
- 先将班次的开始/结束时间配对成结构化数据,避免单独处理两个向量的对应问题
- 给52周循环分配3种班次(因为班次只有3种,用取模运算实现循环)
- 按周匹配班次后,仅替换非NA的
Start和End值,保留原有的NA行
具体实现
1. 构造班次映射表
先把两个班次向量整合成一个数据框,方便后续匹配:
shift_df <- data.frame( shift_id = 1:3, start_time = c("06:00", "08:00", "14:00"), end_time = c("14:00", "16:00", "22:00") )
2. 基础R实现(无需额外包)
适合新手快速理解逻辑:
# 给每周分配对应的班次ID:1-3循环 schedule$shift_id <- (schedule$Week_number - 1) %% 3 + 1 # 合并班次信息到原数据框 schedule <- merge(schedule, shift_df, by = "shift_id", all.x = TRUE) # 替换非NA的Start和End schedule$Start <- ifelse(!is.na(schedule$Start), schedule$start_time, schedule$Start) schedule$End <- ifelse(!is.na(schedule$End), schedule$end_time, schedule$End) # 清理临时列,保留需要的字段 schedule <- schedule[, c("Week_number", "Start", "End")]
3. dplyr实现(更简洁高效)
如果熟悉tidyverse工具链,用这个更直观:
library(dplyr) # 构造班次映射 shift_df <- tibble( shift_id = 1:3, start_time = c("06:00", "08:00", "14:00"), end_time = c("14:00", "16:00", "22:00") ) # 按周匹配班次并替换 schedule <- schedule %>% # 生成循环的班次ID mutate(shift_id = (Week_number - 1) %% 3 + 1) %>% # 关联班次信息 left_join(shift_df, by = "shift_id") %>% # 替换非NA值 mutate( Start = if_else(!is.na(Start), start_time, Start), End = if_else(!is.na(End), end_time, End) ) %>% # 保留目标列 select(Week_number, Start, End)
关键说明
- 循环班次分配:
(Week_number - 1) %% 3 + 1确保第1周用第1种班次,第2周第2种,第3周第3种,第4周回到第1种,以此类推覆盖52周 - 非NA替换:用
ifelse/if_else精准只修改非NA的行,不会破坏原有的NA记录 - 避免嵌套循环:用数据合并的方式替代嵌套循环,代码更简洁,也减少新手容易犯的索引错误
内容的提问来源于stack exchange,提问作者dmitrii
相关产品推荐
相关产品推荐

