2014-12-15 3 views
15

Come fare il seguito (semplice utilizzando sqldf) utilizzando data.table e ottenere esattamente lo stesso risultato:Come eseguire il join su intervalli di date utilizzando data.table?

library(data.table) 

whatWasMeasured <- data.table(start=as.POSIXct(seq(1, 1000, 100), 
    origin="1970-01-01 00:00:00"), 
    end=as.POSIXct(seq(10, 1000, 100), origin="1970-01-01 00:00:00"), 
    x=1:10, 
    y=letters[1:10]) 

measurments <- data.table(time=as.POSIXct(seq(1, 2000, 1), 
    origin="1970-01-01 00:00:00"), 
    temp=runif(2000, 10, 100)) 

## Alternative short names for data.tables 
dt1 <- whatWasMeasured 
dt2 <- measurments 

## Straightforward with sqldf  
library(sqldf) 

sqldf("select * from measurments m, whatWasMeasured wwm 
where m.time between wwm.start and wwm.end") 
+1

Questo risolve il problema? http://stackoverflow.com/questions/5123197/matching-time-a-time-in-the-interval-between-a-start-and-end-time –

+0

@DavidRobinson Grazie. Ho effettivamente visto questa domanda e risposta, ma sfortunatamente il mio volume di dati è enorme e preferirei davvero una soluzione veloce data.table ... – Samo

+0

So che questo è un po 'irrealizzato, ma sono l'unico a ricevere il Dec-31-1969 date? Non dovrebbe essere jan-1-1970? –

risposta

17

È possibile utilizzare la funzione che implementa foverlaps() unisce su intervalli in modo efficiente. Nel tuo caso, abbiamo solo bisogno di una colonna fittizia per measurments.

Nota 1: è necessario installare la versione di sviluppo di data.table - v1.9.5 come un bug con foverlaps() è stato risolto lì. È possibile trovare le istruzioni di installazione here.

Nota 2: Chiamerò whatWasMeasured = dt1 e measurments = dt2 qui per convenienza.

require(data.table) ## 1.9.5+ 
dt2[, dummy := time] 

setkey(dt1, start, end) 
ans = foverlaps(dt2, dt1, by.x=c("time", "dummy"), nomatch=0L)[, dummy := NULL] 

Vedi ?foverlaps per maggiori informazioni e this post per un confronto delle prestazioni.

+0

c'è un modo per farla franca con una sorta di% tra% statement? Ha avuto difficoltà a ottenere dt2 [tempo% tra% dt1 [, list (start, end)]] per funzionare come speravo. –

+0

@SerbanTanasa, dai un'occhiata al [post] (http://stackoverflow.com/a/25655497/559784) che ho collegato nella mia risposta. Confronta le prestazioni di una soluzione usando 'between' pure. – Arun

+0

Grazie per la risposta. Grande. Funziona. Molto veloce. L'unico problema minore è che non ama i valori mancanti per l'inizio, la fine o l'ora. forse un trattamento na.rm sarebbe bello avere. Inoltre, quando faccio questo esercizio su dati reali ottengo nel risultato finale due colonne indesiderate aggiuntive denominate "start" e "end" che non ho nemmeno nei dati di input, né i nomi delle chiavi o altro ... – Samo