R语言如何拆分每日营业时间生成周一至周日7个独立时间列
营业时间批量标准化方案
需求背景
需要将10万+条格式不规范的营业时间数据,整理为谷歌营业时间标准格式,示例如下:
Monday 06:00 - 18:00 Tuesday 08:00 - 18:00 ... Sunday Closed
原有实现方案是逐个正则匹配后赋值,存在两个核心问题:
- 匹配结果为NA时会覆盖之前已经匹配到的有效内容
- 逐个写时间范围匹配逻辑,代码冗余可维护性差
快速解决:仅非NA时更新值
如果你暂时不想调整整体逻辑,只需要解决NA覆盖有效内容的问题,直接用dplyr::coalesce函数替换原有赋值逻辑即可:该函数会优先取第一个非NA值,匹配成功就用新值,匹配失败就保留原有值,不会发生覆盖。
示例修改如下:
# 原有赋值写法 # Times$Sunday <- paste(df$V2, df$V3,sep = "-") # 修改为: Times$Sunday <- dplyr::coalesce(paste(df$V2, df$V3,sep = "-"), Times$Sunday)
更优雅的批量处理方案
不用逐条写所有时间范围的正则,提前定义好星期缩写映射,自动解析所有时间区间即可,10万+数据也能高效处理,完整代码如下:
library(stringr) library(dplyr) # 1. 初始化数据 Times <- data.frame(opening_hours = c("Su 09:00-17:00,M-S 08:00-20:00", "Su-S 06:00-23:59", "Su-S 08:00-22:00", "Su 08:00-22:00,M-F 08:30-22:00,S 08:00-22:00", "Su-S 00:00-23:59", "M-F 08:00-22:00", "M-W 08:00-22:00, Th-F 08:00-22:00")) # 2. 定义星期缩写和全称的映射,新增缩写只要更新这个列表即可 week_map <- list( "M" = "Monday", "T" = "Tuesday", "W" = "Wednesday", "Th" = "Thursday", "F" = "Friday", "S" = "Saturday", "Su" = "Sunday" ) week_cols <- unlist(week_map, use.names = F) # 初始化所有星期列为默认Closed Times[, week_cols] <- "Closed" # 3. 拆分每条数据的多个时间区间 time_segments <- str_split(Times$opening_hours, ",\\s*") # 4. 遍历解析每个时间区间,批量更新对应星期的营业时间 for (i in seq_along(time_segments)) { segments <- time_segments[[i]] for (seg in segments) { # 匹配星期范围和时间 seg_match <- str_match(seg, "(?i)([A-Za-z]+)-?([A-Za-z]*)\\s*(\\d{2}:\\d{2})-(\\d{2}:\\d{2})") if (is.na(seg_match[1,1])) next start_wk <- seg_match[1,2] end_wk <- seg_match[1,3] time_str <- paste0(seg_match[1,4], "-", seg_match[1,5]) # 确定当前时间区间适用的星期列表 if (end_wk == "") { # 单天规则,比如Su 09:00-17:00 apply_wks <- week_map[[start_wk]] } else { # 区间规则,比如M-F,取起始到结束之间的所有星期 start_idx <- which(names(week_map) == start_wk) end_idx <- which(names(week_map) == end_wk) apply_wks <- unlist(week_map[start_idx:end_idx], use.names = F) } # 更新对应星期的值,单天规则优先级高于区间规则,不会被覆盖 Times[i, apply_wks] <- time_str } } # 5. 生成谷歌标准格式的营业字符串 Times$standard_hours <- apply(Times[, week_cols], 1, function(x) { paste(names(x), x, sep = " ", collapse = "\n") }) # 查看处理结果示例 cat(Times$standard_hours[1])
运行后输出效果如下:
Monday 08:00-20:00 Tuesday 08:00-20:00 Wednesday 08:00-20:00 Thursday 08:00-20:00 Friday 08:00-20:00 Saturday 08:00-20:00 Sunday 09:00-17:00
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

