2017-10-11 6 views
1

J'ai deux trames de données ayant un nombre différent de lignes et un nombre de colonnes: chacune de ces trames de données a un intervalle de dates. df a une colonne supplémentaire qui indique une sorte d'attribut. Mon but est d'extraire des informations de df (avec les attributs) vers df2 dans certaines conditions. La procédure doit être la suivante:Colonnes correspondant à des intervalles de chevauchement (lubrification)

Pour chaque intervalle de date de df2, vérifiez s'il existe un intervalle dans df qui chevauche l'intervalle de df2. Si oui, créez une colonne dans df2 qui indique les attributs correspondant à l'intervalle de chevauchement de df. Il peut y avoir plusieurs attributs correspondant à un intervalle spécifique de df2.

J'ai créé l'exemple suivant de mes données:

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 

Il en résulte ces trames de données:

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 

Mon trames de données souhaitées ressembler à ceci:

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 

Je regardais déjà dans la fonction int_overlaps() mais ne pouvait pas faire le « balayage à travers tous les intervalles d'une autre colonne » de travail -partie. Si oui, existe-t-il une solution qui utilise l'environnement Tidyr?

Répondre

1

vous pouvez créer une simple boucle pour passer par les valeurs individuelles utilisant tidyverse's package lubridate et la fonction int_overlaps() d'une manière, de df2$Interval aiment suit:

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=", ") 
} 

donnant les résultats suivants

#  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 

J'ai laissé la stratégie NA ouverte, mais la ligne supplémentaire df2$Matched_Attr[df2$Matched_Attr==""]<-NA retournerait le résultat exact souhaité.

En réponse à votre commentaire (seulement effectuer l'action ci-dessus lorsqu'un df $ ID [i] == DF2 $ ID [i] condition est remplie), le inplementation suit:

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

Merci beaucoup pour la répondre! Puis-je adapter la procédure mentionnée ci-dessus à un cas dans lequel j'ai une autre colonne (caractère) dans laquelle je veux que la boucle fonctionne? Disons que la nouvelle colonne dans df et df2 est appelée "ID" et je veux seulement exécuter la procédure si l'ID correspond? –

+0

Quel type de correspondance voulez-vous dire exactement? Pouvez-vous donner un court exemple? Si df2ID [1] == df $ ID [1] alors calcule le Matche_Attr? Ou quelque chose de similaire? –

+0

Oui. "Si df2ID [1] == df $ ID [1]" est la condition. Dans un réglage dplyr, j'aurais juste utilisé group_by (ID) mais je ne sais pas comment traduire ceci à notre boucle utilisée ici. –