匹配具有重叠间隔的列(lubridate)

时间:2017-10-11 10:04:11

标签: r tidyr lubridate

我有两个不同行数和列数的数据帧:这些数据帧中的每一个都有一个日期间隔。 df有一个附加列,表示某种属性。我的目标是在某些条件下从df(带属性)中提取信息到df2。程序应如下:

对于df2的每个日期间隔,检查df中是否有与df2的间隔重叠的间隔。如果是,则在df2中创建一个列,表示与df的重叠间隔匹配的属性。可以有多个属性与df2的特定间隔匹配。

我创建了以下数据示例:

library(lubridate)
date1 <- as.Date(c('2017-11-1','2017-11-1','2017-11-4'))
date2 <- as.Date(c('2017-11-5','2017-11-3','2017-11-5'))
df <- data.frame(matrix(NA,nrow=3, ncol = 4)) 
names(df) <- c("Begin_A", "End_A", "Interval", "Attribute")
df$Begin_A <-date1
df$End_A <-date2

df$Interval <-df$Begin_A %--% df$End_A
df$Attribute<- as.character(c("Attr1","Attr2","Attr3"))

### Second df:

date1 <- as.Date(c('2017-11-2','2017-11-5','2017-11-7','2017-11-1'))
date2 <- as.Date(c('2017-11-3','2017-11-6','2017-11-8','2017-11-1'))
df2 <- data.frame(matrix(NA,nrow=4, ncol = 3)) 
names(df2) <- c("Begin_A", "End_A", "Interval")
df2$Begin_A <-date1
df2$End_A <-date2
df2$Interval <-df2$Begin_A %--% df2$End_A

这导致了这些数据框:

DF:

Begin_A      End_A        Interval                         Attribute
2017-11-01   2017-11-05   2017-11-01 UTC--2017-11-05 UTC   Attr1
2017-11-01   2017-11-03   2017-11-01 UTC--2017-11-03 UTC   Attr2
2017-11-04   2017-11-05   2017-11-04 UTC--2017-11-05 UTC   Attr3

DF2:

Begin_A      End_A        Interval
2017-11-02   2017-11-03   2017-11-02 UTC--2017-11-03 UTC
2017-11-05   2017-11-06   2017-11-05 UTC--2017-11-06 UTC
2017-11-07   2017-11-08   2017-11-07 UTC--2017-11-08 UTC
2017-11-01   2017-11-01   2017-11-01 UTC--2017-11-01 UTC

我想要的数据框如下所示:

Begin_A      End_A        Interval                         Matched_Attr 
2017-11-02   2017-11-03   2017-11-02 UTC--2017-11-03 UTC   Attr1;Attr2
2017-11-05   2017-11-06   2017-11-05 UTC--2017-11-06 UTC   Attr1;Attr3
2017-11-07   2017-11-08   2017-11-07 UTC--2017-11-08 UTC   NA
2017-11-01   2017-11-01   2017-11-01 UTC--2017-11-01 UTC   Attr1;Attr2

我已经查看过int_overlaps()函数,但无法进行“扫描另一列的所有间隔” - 部分工作。 如果是,是否有任何解决方案可以利用tidyr环境?

1 个答案:

答案 0 :(得分:1)

使用tidyverse的lubridate包及其函数int_overlaps(),您可以创建一个简单的for循环来遍历df2$Interval的各个值,如下所示:

df2$Matched_Attr <- NA
for(i in 1:nrow(df2)){
  df2$Matched_Attr[i] <-  paste(df$Attribute[int_overlaps(df2$Interval[i], df$Interval)], collapse=", ")
}

给出以下结果

#     Begin_A      End_A                       Interval Matched_Attr
#1 2017-11-02 2017-11-03 2017-11-02 UTC--2017-11-03 UTC Attr1, Attr2
#2 2017-11-05 2017-11-06 2017-11-05 UTC--2017-11-06 UTC Attr1, Attr3
#3 2017-11-07 2017-11-08 2017-11-07 UTC--2017-11-08 UTC             
#4 2017-11-01 2017-11-01 2017-11-01 UTC--2017-11-01 UTC Attr1, Attr2

我打开了NA策略,但额外的行df2$Matched_Attr[df2$Matched_Attr==""]<-NA会返回确切的预期结果。

在回复您的评论时(仅在满足df $ ID [i] == df2 $ ID [i]条件时执行上述操作),实现如下:

library(lubridate)
#df
df <- data.frame(Attribute=c("Attr1","Attr2","Attr3"),
                 ID = c(3,2,1),
                 Begin_A=as.Date(c('2017-11-1','2017-11-1','2017-11-4')),
                 End_A=as.Date(c('2017-11-5','2017-11-3','2017-11-5')))
df$Interval <- df$Begin_A %--% df$End_A

### Second df:
df2 <- data.frame(ID=c(3,4,5),
                  Begin_A=as.Date(c('2017-11-2','2017-11-5','2017-11-7')),
                  End_A=as.Date(c('2017-11-3','2017-11-6','2017-11-8')))
df2$Interval <- df2$Begin_A %--% df2$End_A

df2$Matched_Attr <- NA
for(i in 1:nrow(df2)){
  if(df2$ID[i]==df$ID[i]){
  df2$Matched_Attr[i] <-  paste(df$Attribute[int_overlaps(df2$Interval[i], df$Interval)], collapse=", ")
  }
}
print(df2)
#  ID    Begin_A      End_A                       Interval Matched_Attr
#1  3 2017-11-02 2017-11-03 2017-11-02 UTC--2017-11-03 UTC Attr1, Attr2
#2  4 2017-11-05 2017-11-06 2017-11-05 UTC--2017-11-06 UTC         <NA>
#3  5 2017-11-07 2017-11-08 2017-11-07 UTC--2017-11-08 UTC         <NA>
相关问题