字符串转数组:开放时间(一周以上)

String conversion to array: Opening hours (over a week)

我已经完成了 OSM 提取,在这里您可以看到 R 中每个对象的开放时间列“osm_openin”。 它具有以下结构:

我希望一周中的每一天都有新的列,带有符号“X”——如果它不是全天开放——或者当天的相应开放时间“07:00 - 21:00".

我的解决方案:

首先,我正在考虑使用星期“Mo = 1”、“Tu = 2”...“Su = 7”的代表值。重要的是,如果 day/value 本身没有被明确提及,而是存在于一个时间间隔中。

对于每个值,我都在列中搜索它的存在。 如果找到该值,我将在之后直接使用开放时间(不知道要使用哪个 R 命令) 如果不是,则该值必须在一个区间内。例如“2”(星期二)不存在,那么脚本需要实现星期二在Mo-Sa之间。 (不知道该使用哪种方法)。

Public假期不重要。

有什么解决方案的建议吗?

谢谢。

我不知道最好的方法,但也许我可以帮助你。 首先我们需要创建工作日数组:

wdays <- c("Mo", "Tu", "We", "Th", "Fr", "Sa", "Su")

现在让我们编写代码,将文本从 "Mo,We-Fr" 转换为向量 c(1, 3, 4, 5)。算法:

  1. 删除节假日信息("PH", "SH");
  2. 将工作日名称替换为数字("Mo" --> 1"Tu" --> 2 等);
  3. - 替换为 :。例如,3-5 将是 3:5 并且它是 R-style 代码;
  4. 在开头添加c(,在结尾添加)。例如,1,3:5 将是 c(1, 3:5)
  5. c(1, 3:5) 是 R-style 向量,我们可以通过文本创建向量 (eval(parse(text = "c(1, 3:5)")))。

完整代码:

GetWDays <- function(x, wdays) {
    holi <- c("PH", "SH")
    x <- gsub(paste0("(,|^)", holi, collapse = "|"), "", x) #delete holidays
    
    for (i in 1:7) {
        x <- gsub(wdays[i], i, x)
    }
    
    x <- gsub("-", ":", x)
    x <- paste0("c(", x, ")")
    
    wday_idx <- eval(parse(text = x))
    return(wday_idx)
}

让我们创建一个函数,将营业时间(如 "Mo-Fr 6:30-19:00;Sa 09:00-17:00;Su,PH 09:00-15:00")作为输入,returns data.frame 有 7 列(每个工作日)。算法:

  1. ; 拆分文本;现在我们将处理文本的一部分(例如,"Mo-Fr 6:30-19:00");
  2. 将文本拆分为 (space); "Mo-Fr 6:30-19:00" --> "Mo-Fr""6:30-19:00"
  3. 我们将第一部分 ("Mo-Fr") 放入 GetWDays 并从第二部分制作矢量(它的大小将与第一部分大小相同)。示例:"Mo-Fr" --> c(1,2,3,4,5), "6:30-19:00" --> rep("6:30-19:00", 5);
  4. 从 2 个向量(DayTime)生成 data.frame;
  5. 对第一步中的每个部分使用 bind_rows。现在我们有很大的 data.frame,但是有些工作日可能会丢失,有些工作日可能在 Time;
  6. 列中有 "Off"
  7. 因此,为缺少的工作日添加行(按 merge)并将“Off”和 NA 替换为 "X"(如您所愿);
  8. 转置 data.frame 和 return

完整代码:

GetTimetable <- function(x) {
    wdays <- c("Mo", "Tu", "We", "Th", "Fr", "Sa", "Su")
    
    
    tmp <- strsplit(strsplit(x, ";")[[1]], " ")
    tmp <- lapply(tmp, function(x) {Day <- GetWDays(x[1], wdays); data.frame(Day, Time = rep(x[2], length(Day)))})
    tmp <- bind_rows(tmp) %>% arrange(Day) %>% as.data.frame()
    tmp <- merge(data.frame(Day = 1:7), tmp, all.x = T, by = "Day")
    tmp$Time[is.na(tmp$Time) | tmp$Time == "Off"] = "X"
    
    tmp <- tmp %>% t() %>% "["(2, ) %>% as.list() %>% setNames(wdays) %>% bind_cols()
    return(tmp)
}

如果您想为每一行应用 GetTimetable,您可以使用此代码:

df_time <- df$osm_openning %>% lapply(GetTimetable) %>% bind_rows()

如果您想将此 data.frame 添加到您的数据中,您可以这样做:

df <- bind_cols(df, df_time)