La ragione per cui t_id = 1
non si presenta in uscita è perché un rotolamento join prende la riga in cui la combinazione di tasti posta per ultima. Dalla documentazione (sottolineatura mia):
Vale per l'ultima colonna di join, in genere una data, ma può essere eventuali lacune variabile ordinata, irregolari e compreso. Se roll = TRUE e i numeri di riga corrispondono a tutti tranne l'ultima colonna x join e il suo valore nella colonna ultimo join cade in un intervallo (anche dopo l'ultima osservazione di in x per quel gruppo), quindi il valore prevalente in x è rotolato in avanti. Questa operazione è particolarmente veloce utilizzando una ricerca binaria modificata . L'operazione è anche nota come ultima osservazione trasportata in avanti (LOCF).
Consideriamo serie di dati un po 'più grandi:
> DT
t_id airport thisTime
1: 1 a 5.1
2: 4 a 5.1
3: 3 a 5.1
4: 2 d 6.2
5: 5 d 6.2
> DT_LU
f_id airport thisTime
1: 1 a 6
2: 2 a 6
3: 2 a 8
4: 1 b 7
5: 1 c 8
6: 2 d 7
7: 1 d 9
Quando si esegue un rotolamento join proprio come nella tua domanda:
DT[DT_LU, nomatch=0, roll=Inf]
si ottiene:
t_id airport thisTime f_id
1: 3 a 6 1
2: 3 a 6 2
3: 3 a 8 2
4: 5 d 7 2
5: 5 d 9 1
Come puoi vedere, da entrambi i tasti combinazione a, 5.1
e d, 6.2
l'ultima riga viene utilizzata per il datatable unito. Poiché si utilizza Inf
come valore di rollover, tutti i valori futuri vengono incorporati nel datatable risultante. Quando si utilizza:
DT[DT_LU, nomatch=0, roll=1]
si vede che solo il primo valore in futuro è incluso:
t_id airport thisTime f_id
1: 3 a 6 1
2: 3 a 6 2
3: 5 d 7 2
Se si desidera che il f_id
's per per tutte le combinazioni di airport
& thisTime
dove DT$thisTime
è inferiore a DT_LU$thisTime
, è possibile ottenere ciò creando una nuova variabile (o sostituendo lo esistente thisTime
) tramite il ceiling
funzione. Un esempio in cui creo una variabile nuova thisTime2
e poi fare un normale unirsi con DT_LU
:
DT[, thisTime2 := ceiling(thisTime)]
setkey(DT, airport, thisTime2)[DT_LU, nomatch=0]
che dà:
t_id airport thisTime thisTime2 f_id
1: 1 a 5.1 6 1
2: 4 a 5.1 6 1
3: 3 a 5.1 6 1
4: 1 a 5.1 6 2
5: 4 a 5.1 6 2
6: 3 a 5.1 6 2
7: 2 d 6.2 7 2
8: 5 d 6.2 7 2
applicate ai dati che hai fornito:
> dt[, thisTime2 := ceiling(thisTime)]
> setkey(dt, airport, thisTime2)[dt_lookup, nomatch=0]
t_id airport thisTime thisTime2 f_id
1: 1 a 5.1 6 1
2: 3 a 5.1 6 1
3: 1 a 5.1 6 2
4: 3 a 5.1 6 2
Quando si desidera includere tutti i valori futuri anziché solo il primo o ne, è necessario un approccio un po 'diverso per il quale è necessario il funzionalità i.col
(che non è ancora documentato):
: primo set la chiave per solo le airport
colonne:
setkey(DT, airport)
setkey(DT_LU, airport)
: Utilizzare la funzionalità di i.col
(che non è ancora documentato) in j
per ottenere ciò che si vuole come segue:
DT1 <- DT_LU[DT, .(tid = i.t_id,
tTime = i.thisTime,
fTime = thisTime[i.thisTime < thisTime],
fid = f_id[i.thisTime < thisTime]),
by=.EACHI]
.210
questo ti dà:
> DT1
airport tid tTime fTime fid
1: a 1 5.1 6 1
2: a 1 5.1 6 2
3: a 1 5.1 8 2
4: a 4 5.1 6 1
5: a 4 5.1 6 2
6: a 4 5.1 8 2
7: a 3 5.1 6 1
8: a 3 5.1 6 2
9: a 3 5.1 8 2
10: d 2 6.2 7 2
11: d 2 6.2 9 1
12: d 5 6.2 7 2
13: d 5 6.2 9 1
Qualche spiegazione: Nel caso in cui si stanno unendo due DataTable dove gli stessi columnnames vengono utilizzati, è possibile fare riferimento alle colonne del DataTable in i
facendo precedere il columnnames con i.
. Ora è possibile confrontare thisTime
da DT
con thisTime
da DT_LU
.Con by = .EACHI
si assicura che tutte le combinazioni per le condizioni in attesa siano incluse nel datatable risultante.
In alternativa, è possibile ottenere lo stesso con:
DT2 <- DT_LU[DT, .(airport=i.airport,
tid=i.t_id,
tTime=i.thisTime,
fTime=thisTime[i.thisTime < thisTime],
fid=f_id[i.thisTime < thisTime]),
allow.cartesian=TRUE]
che dà lo stesso risultato:
> identical(DT1, DT2)
[1] TRUE
Se solo si desidera includere i valori futuri entro un certo limite, è possibile utilizzare:
DT1 <- DT_LU[DT,
{
idx = i.thisTime < thisTime & thisTime - i.thisTime < 2
.(tid = i.t_id,
tTime = i.thisTime,
fTime = thisTime[idx],
fid = f_id[idx])
},
by=.EACHI]
che dà:
> DT1
airport tid tTime fTime fid
1: a 1 5.1 6 1
2: a 1 5.1 6 2
3: a 4 5.1 6 1
4: a 4 5.1 6 2
5: a 3 5.1 6 1
6: a 3 5.1 6 2
7: d 2 6.2 7 2
8: d 5 6.2 7 2
Quando si confronta il risultato precedente, si vede che ora le righe 3, 6, 9, 10 e 12 sono state rimosse.
dati:
DT <- data.table(t_id = c(1,4,2,3,5),
airport = c("a","a","d","a","d"),
thisTime = c(5.1, 5.1, 6.2, 5.1, 6.2),
key=c("airport","thisTime"))
DT_LU <- data.table(f_id = c(rep(1,4),rep(2,3)),
airport = c("a","b","c","d","a","d","e"),
thisTime = c(6,7,8,9,6,7,8),
key=c("airport","thisTime"))
bello vedere questo post. Lo stavo provando da un po 'di tempo .. – akrun
Grande spiegazione - "un join rotolante prende la riga dove si trova la combinazione di tasti per ultima" - è stata la chiave per la mia comprensione grazie. – tospig
E il tuo esempio 'ceiling' funziona bene in questa situazione, ma mi aspetto che non funzioni quando il valore di' dt $ thisTime2' è superiore all'unità di tempo '1' lontano dal valore' dt_lookup $ thisTime' che sta cercando di far coincidere a, quindi potrei dover trovare un'alternativa? – tospig