2017-08-18 9 views
0

Tout fonctionne, mais il est très lent itérer avec deux pour les boucles.jointure basée sur une colonne et l'heure la plus proche qui n'est pas terminée

Fondamentalement 2 trames de données, une avec et ID et l'heure de l'événement. L'autre avec divers ID et lectures (valeur et horodatage) toutes les 10 secondes environ. J'essaie de joindre une table à une autre en faisant correspondre l'ID, et l'heure à un intervalle spécifique avant l'heure de l'événement, disons 20 secondes.

Alternativement, les données sont dans un serveur SQL Oracle, ce qui si je pouvais faire les jointures de table dans SQL qui fonctionne aussi.

readingdf <- data.frame(sensorID = c('100001','100001','100001','100001','100002','100002','100002','100002'), 
        readTime = as.POSIXct(c("2017-07-24 04:08:09 EDT","2017-07-24 04:08:19 EDT", 
        "2017-07-24 04:08:29 EDT","2017-07-24 04:08:39 EDT","2017-07-24 04:08:09 EDT","2017-07-24 04:08:19 EDT", 
        "2017-07-24 04:08:29 EDT","2017-07-24 04:08:39 EDT"),tz="EST"), 
        Value = c('17.5','15.6','12.9','12.1','22.2', '24.5','19.7','20.1')) 


df <- data.frame(sensorID = c('100001','100002','100001','100002','100001','100002','100001','100001'), 
        eventTime = as.POSIXct(c("2017-07-24 04:08:23 EDT","2017-07-24 04:08:25 EDT","2017-07-24 07:04:40 EDT", 
        "2017-07-24 02:19:30 EDT","2017-07-24 04:37:08 EDT","2017-07-24 04:19:59 EDT","2017-07-24 03:26:49 EDT", 
        "2017-07-24 03:58:17 EDT"),tz="EST")) 
+0

que voulez-vous dire intervalle 20 secondes? S'il vous plaît élaborer. Si possible, pouvez-vous coller la sortie attendue ici? Merci – Onyambu

+0

Si vos tables sont grandes, vous devriez faire la jointure dans le serveur Oracle: utilisez quelque chose comme 'select * from t1 jointure interne t2 sur (t1.sensorID = t2.sensorID et readTime <= eventTime et f (eventTime, readTime) <= 20) ',' f' étant une fonction donnant la différence entre deux datetime en secondes (il faut le définir). – Scarabee

Répondre

0

Nous pouvons créer une nouvelle colonne, readTime_expand, montrant les 20 secondes de readTime. Après cela, effectuez une jointure basée sur sensorID avec eventTime = readTime_expand. df2 est la sortie finale.

library(tidyverse) 

readingdf2 <- readingdf %>% 
    mutate(readTime_end = readTime + 20) %>% 
    mutate(readTime_expand = map2(readTime, readTime_end, function(x, y){ 
    return(seq(x, y, by = 1)) 
    })) %>% 
    unnest() 

df2 <- df %>% 
    left_join(readingdf2, by = c("sensorID", "eventTime" = "readTime_expand")) 

df2 
    sensorID   eventTime   readTime Value  readTime_end 
1 100001 2017-07-24 04:08:23 2017-07-24 04:08:09 17.5 2017-07-24 04:08:29 
2 100001 2017-07-24 04:08:23 2017-07-24 04:08:19 15.6 2017-07-24 04:08:39 
3 100002 2017-07-24 04:08:25 2017-07-24 04:08:09 22.2 2017-07-24 04:08:29 
4 100002 2017-07-24 04:08:25 2017-07-24 04:08:19 24.5 2017-07-24 04:08:39 
5 100001 2017-07-24 07:04:40    <NA> <NA>    <NA> 
6 100002 2017-07-24 02:19:30    <NA> <NA>    <NA> 
7 100001 2017-07-24 04:37:08    <NA> <NA>    <NA> 
8 100002 2017-07-24 04:19:59    <NA> <NA>    <NA> 
9 100001 2017-07-24 03:26:49    <NA> <NA>    <NA> 
10 100001 2017-07-24 03:58:17    <NA> <NA>    <NA>