查找特定时间可用的所有ID

时间:2016-04-26 03:20:55

标签: r data.table

我有一个二进制矩阵,可以指示一个人(ID)是否一次可用来完成工作。

示例矩阵
08:00 08:30 09:00 09:30 10:00 10:30 11:00 11:30 12:00 12:30 13:00 13:30 14:00 14:30 15:00 15:30 16:00 16:30 17:00 17:30 18:00 18:30 19:00
1     1     1     1     1     1     0     1     1     1     1     0     1     1     1     1     1     1     1     0     0     0     0     0
2     1     1     1     1     1     0     1     1     1     1     0     1     1     1     1     1     1     1     0     0     0     0     0
3     0     1     1     1     1     1     0     1     1     1     1     0     1     1     1     1     1     1     1     0     0     0     0
4     0     1     1     1     1     1     0     1     1     1     1     0     1     1     1     1     1     1     1     0     0     0     0
5     0     0     1     1     1     1     1     0     1     1     1     1     0     1     1     1     1     1     1     1     0     0     0
6     0     0     1     1     1     1     1     0     1     1     1     1     0     1     1     1     1     1     1     1     0     0     0
  19:30
1     0
2     0
3     0
4     0
5     0
6     0

行名称代表ID,显示的时间是ID可用的时间。在该示例中,ID 1和2在8:00开始工作,并且具有在10:30-11:00,13:00-13:30的特定休息时段。半小时后开始的人3和4从11:00-11:30,13:30-14:00休息。这是为了确保有人可以从事任何特定时刻的工作。

dput(矩阵)

structure(c(1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 
0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0), .Dim = c(6L, 24L), .Dimnames = list(c("1", "2", "3", "4", 
"5", "6"), c("08:00", "08:30", "09:00", "09:30", "10:00", "10:30", 
"11:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", 
"14:30", "15:00", "15:30", "16:00", "16:30", "17:00", "17:30", 
"18:00", "18:30", "19:00", "19:30")))

另一个数据集有" ID"与他们的开始时间

data1 <- data.frame(ID = 1:6, Start_Time = c("8:00", "8:00", "8:30", 
             "8:30", "9:00", "9:30"), stringsAsFactors=FALSE)

第三个数据集将包含特定任务的开始和结束时间

 data2 <- data.frame(Start = c("8:01", "9:35", "10:42", "11:25", "14:22", 
    "17:20", "18:19"), End = c("8:22", "9:42", "11:20", "11:32", 
    "14:35", "18:15", "18:25"), stringsAsFactors=FALSE)

我正在尝试在data2中创建一个列,该列根据data2中的开始时间提供可用于执行任务的ID。预期的输出是

data2$IdsAvail <- c("1, 2", "1, 2, 3, 4, 5, 6", "3, 4, 5, 6", 
  "1, 2, 5, 6", "1, 2, 3, 4", "3, 4, 5, 6", NA)

看起来如下

DATA2

 Start   End         IdsAvail
1  8:01  8:22             1, 2
2  9:35  9:42 1, 2, 3, 4, 5, 6
3 10:42 11:20       3, 4, 5, 6
4 11:25 11:32       1, 2, 5, 6
5 14:22 14:35       1, 2, 3, 4
6 17:20 18:15       3, 4, 5, 6
7 18:19 18:25             <NA>

尝试将ID与矩阵中的时间匹配,但无法找到方法。在一个人工作的时间范围内,也可能有两个工作岗位。我在这里没有考虑到这一点。这只是为了根据矩阵获得初始ID。

编辑:以下@Audiophile的解决方案适用于该示例,但它会在此处发出重复警告

availability <- merge(availability,data2,by.x = 'time',by.y = 'slot',all.y = T)

我必须使用allow.cartesian才能在原始数据集中使用它。我的数据集有大约2000行,使用合并后它会产生大约20000行。使用此示例的上述merge步骤也会提供与“可用性”中不同的行数。或者&#39; data2&#39;。还有其他方法,即使用foverlaps中的data.table吗?

1 个答案:

答案 0 :(得分:2)

确定每个人可用的插槽,然后将其与任务列表合并:

library(tidyr)
library(dplyr)

#Convert your availability matrix (mat1) to a data frame
df <- as.data.frame(mat1)
df$ID <- rownames(df)

#Reshape the availability dataset
availability <- df %>%
  gather(time,available,-ID) %>%
  filter(available==1) %>%
  mutate(time = as.POSIXct(time,format = "%H:%M"))

data1$Start_Time <- as.POSIXct(data1$Start_Time,format = "%H:%M")
data2$Start <- as.POSIXct(data2$Start,format = "%H:%M")

#Use start times to refine availability dataset
availability <- merge(availability,data1,by = "ID")
availability <- availability %>%
  filter(time>=Start_Time) %>%
  select(ID,time)

#Round task time to nearest half hour slot
data2$slot <- as.POSIXct(floor(as.double(data2$Start)/1800)*1800,
                         format = "%H:%M",origin = as.POSIXct('1970-01-01',tz='UTC'))


availability <- merge(availability,data2,by.x = 'time',by.y = 'slot',all.y = T)

availability <- availability %>%
  select(Start,End,ID) %>%
  arrange(Start,ID) %>%
  group_by(Start,End) %>%
  summarise(IdsAvail = toString(ID)) %>%
  ungroup() %>%
  mutate(Start = format(Start,"%H:%M"))