我假设您有一个 start_hour 和 end_hour 为整数的输入表,例如:
# applicant day start_hour end_hour
#1 a monday 9 10
#2 a monday 12 12
#3 a monday 14 16
#4 a monday 17 18
您可以使用seq 查找开始和结束之间的所有时间。以下代码中的想法是生成一个带有开放时间 (dt_open_hours) 的data.table 和一个带有所有可能时间的data.table (dt_all_hours)(使用输入数据中的申请人和天数)。通过合并两个 data.tables,生成的表将包含 applicant、day 和 hour 的所有可能组合,但状态(打开/未打开)将仅来自 dt_open_hours。最后一步是将缺失值 (NA) 转换为“未打开”:
library(data.table)
dt <- structure(list(applicant = structure(c(1L, 1L, 1L, 1L), .Label = "a", class = "factor"),
day = structure(c(1L, 1L, 1L, 1L), .Label = "monday", class = "factor"),
start_hour = c(9L, 12L, 14L, 17L), end_hour = c(10L, 12L,
16L, 18L)), .Names = c("applicant", "day", "start_hour",
"end_hour"), class = "data.frame", row.names = c(NA, -4L))
# Convert to data.table
setDT(dt)
# Assign row_id unique row_ids for seq to work on one row at a time
dt[, row_id := seq(1, nrow(dt))]
# Convert start and end hour into sequence of hours between start and end
dt_open_hours <- dt[, .(state = "Open",
hour = as.integer(seq(from = start_hour, to = end_hour, by = 1))),
by = .(row_id, applicant, day)]
# Remove row_id column
dt_open_hours[, row_id := NULL]
# Generate data.table with all combinations of applicant, day and hour
dt_all_hours <- CJ(applicant = unique(dt_open_hours[, applicant]),
day = unique(dt_open_hours[, day]), hour = seq(1, 24))
# Merge
out <- dt_open_hours[dt_all_hours, on=.(applicant, day, hour)]
out[is.na(state), state := "Not Open"]
out data.table 如下所示:
# applicant day state hour
# 1: a monday Not Open 1
# 2: a monday Not Open 2
# 3: a monday Not Open 3
# 4: a monday Not Open 4
# 5: a monday Not Open 5
# 6: a monday Not Open 6
# 7: a monday Not Open 7
# 8: a monday Not Open 8
# 9: a monday Open 9
#10: a monday Open 10
#11: a monday Not Open 11
#12: a monday Open 12
#13: a monday Not Open 13
#14: a monday Open 14
#15: a monday Open 15
#16: a monday Open 16
#17: a monday Open 17
#18: a monday Open 18
#19: a monday Not Open 19
#20: a monday Not Open 20
#21: a monday Not Open 21
#22: a monday Not Open 22
#23: a monday Not Open 23
#24: a monday Not Open 24
# applicant day state hour
更新:使用以下更新的输入data.frame:
DayOfWeekStr Applicant starthour endhour locationid
1 Friday Natan's Catering 12 13 437207
2 Friday Linda's Catering 10 15 760539
3 Wednesday Mang Hang Catering 12 13 559779
4 Sunday Tacos Santana 17 22 453014
5 Friday Breaking Bread Inc. 14 18 934995
对代码进行了一些修改(除了使用更新后的输入 data.frame 中提供的列名),主要是为了合并locationid 变量:dt_open_hours 包含starthour 和endhour 之间的小时数对于Applicant、DayOfWeekStr、locationid(locationid 是新的)和dt_all_hours 的每个唯一组合,对于Applicant、DayOfWeekStr、locationid 的相同唯一组合,包含小时 1 到 24 . dt_open_hours 和 dt_all_hours 的合并是在 Applicant、DayOfWeekStr、locationid 和 hour 上完成的(locationid 是新的)。
library(data.table)
dt <- structure(list(DayOfWeekStr = c("Friday", "Friday", "Wednesday",
"Sunday", "Friday"), Applicant = c("Natan's Catering", "Linda's Catering",
"Mang Hang Catering", "Tacos Santana", "Breaking Bread Inc."),
starthour = c(12L, 10L, 12L, 17L, 14L), endhour = c(13L,
15L, 13L, 22L, 18L), locationid = c(437207L, 760539L, 559779L,
453014L, 934995L)), .Names = c("DayOfWeekStr", "Applicant",
"starthour", "endhour", "locationid"), row.names = c(NA, -5L),
class = "data.frame")
# Convert to data.table
setDT(dt)
# Assign row_id unique row_ids for seq to work on one row at a time
dt[, row_id := seq(1, nrow(dt))]
# Convert start and end hour into sequence of hours between start and end
dt_open_hours <- dt[, .(state = "Open",
hour = as.integer(seq(from = starthour, to = endhour, by = 1))),
by = .(row_id, Applicant, DayOfWeekStr, locationid)]
# Remove row_id column
dt_open_hours[, row_id := NULL]
# Generate data.table with all combinations of applicant, day and hour
dt_all_hours <- dt[, .(hour = seq(1, 24)),
by = . (Applicant, DayOfWeekStr, locationid)]
# Merge
out <- dt_open_hours[dt_all_hours,
on=.(Applicant, DayOfWeekStr, locationid, hour)]
out[is.na(state), state := "Not Open"]