2016-04-26 135 views
1

我有一个二进制矩阵,用于指示某个人(ID)是否一次可用于执行任务。示例矩阵是在特定时间查找所有可用的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和ID 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中开始时间。预期的输出是

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) 

它看起来像下面

数据2

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步骤也给出不同于“可用性”或“数据2”的行数。是否有其他方法,即使用data.tablefoverlaps

回答

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")) 
+0

感谢您的答复。它在这个例子中工作正常,但在原始数据集中运行'merge(available,data2,by.x ='time',by.y ='slot',all.y = T)'时显示重复错误。所以,我必须使用'allow.cartesian = TRUE'有没有简洁的方法? – kraj

相关问题