2017-10-11 69 views
1

我有两个不同行数和列数的数据框:每个数据框都有一个日期间隔。 df有一个额外的列表示某种属性。我的目标是在某些条件下从df(带有属性)中将信息提取到df2。程序应该如下:重叠间隔的匹配列(lubridate)

对于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

使用tidyverse's lubridate包和it's功能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]条件被满足),则inplementation如下:

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

非常感谢对于回答!我是否可以将上述过程适用于我想要循环运行的另一个(字符)列的情况?假设df和df2中的新列被称为“ID”,并且我只想在ID匹配的情况下运行该过程? –

+0

你的意思是什么样的匹配?你能举一个简单的例子吗?如果df2ID [1] == df $ ID [1],那么计算Matche_Attr?或者类似的东西? –

+0

是的。 “如果df2ID [1] == df $ ID [1]”是条件。在dplyr设置中,我只会使用group_by(ID),但我不知道如何将其转换为我们在此处使用的循环。 –