Rolling join na danych.tabela z duplikatami kluczy
Próbuję zrozumieć rolling joins
w data.table
. Dane do odtworzenia tego podano na końcu.
Podane dane."tabela transakcji w porcie lotniczym w danym czasie": {]}
> dt
t_id airport thisTime
1: 1 a 5.1
2: 3 a 5.1
3: 2 a 6.2
(Uwaga t_ids
1 i 3 mają to samo lotnisko i czas)
I tabela przelotu z lotnisk:
> dt_lookup
f_id airport thisTime
1: 1 a 6
2: 2 a 6
3: 1 b 7
4: 1 c 8
5: 2 d 7
6: 1 d 9
7: 2 e 8
> tables()
NAME NROW NCOL MB COLS KEY
[1,] dt 3 3 1 t_id,airport,thisTime airport,thisTime
[2,] dt_lookup 7 3 1 f_id,airport,thisTime airport,thisTime
Chciałbym dopasować wszystkie transakcje do wszystkich następnych możliwych lotów odlatujących z tego lotniska, aby dać:
t_id airport thisTime f_id
1 a 6 1
1 a 6 2
3 a 6 1
3 a 6 2
Więc pomyślałem, że to praca:
> dt[dt_lookup, nomatch=0,roll=Inf]
t_id airport thisTime f_id
1: 3 a 6 1
2: 3 a 6 2
Ale nie zwrócił transakcji t_id == 1
.
Z dokumentacji jest napisane:
Zazwyczaj nie powinno być duplikatów w kluczu x,...
Jednak mam duplikaty w moim 'x key' (mianowicie airport
& thisTime
), i nie do końca widzę/rozumiem, co się dzieje, co oznacza t_id = 1
zostaje usunięte z wyjścia.
Czy ktoś może rzucić trochę światła na to, dlaczego t_id = 1
nie jest zwracany, i jak Mogę dostać join do pracy dla kiedy mam duplikaty?
Dane
library(data.table)
dt <- data.table(t_id = seq(1:3),
airport = c("a","a","a"),
thisTime = c(5.1,6.2, 5.1), key=c( "airport","thisTime"))
dt_lookup <- 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"))
1 answers
Powodem, dla którego t_id = 1
nie pojawia się na wyjściu, jest to, że połączenie toczne zajmuje wiersz, w którym kombinacja klawiszy występuje jako ostatnia. Z dokumentacji (podkreślenie moje):
Rozważmy nieco większe zbiory danych:]}Odnosi się do ostatniej kolumny join, zazwyczaj jest to data, ale może być dowolna uporządkowane zmienne, nieregularne i zawierające luki. If roll = TRUE, a i ' S wiersz pasuje do wszystkich poza ostatnią kolumną x join, a jego wartość w ostatnio dołączam kolumnę spada w lukę (również po ostatnim obserwacja W x dla tego Grupa), wtedy Dominująca wartość w x jest / align = "left" / Operacja ta jest szczególnie szybka przy użyciu zmodyfikowanego wyszukiwanie binarne. operacja znana jest również jako ostatnia obserwacja forward (LOCF).
> 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
Kiedy wykonujesz Rolling join tak jak w twoim pytaniu:
DT[DT_LU, nomatch=0, roll=Inf]
Otrzymujesz:
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
Jak widać, zarówno z kombinacji klawiszy a, 5.1
jak i d, 6.2
ostatni wiersz jest używany do / align= "left" / Ponieważ używasz Inf
jako wartości roll, wszystkie przyszłe wartości są włączone do wynikowego datatable. Kiedy używasz:
DT[DT_LU, nomatch=0, roll=1]
Widzisz, że zawiera się tylko pierwsza wartość w przyszłości:
t_id airport thisTime f_id
1: 3 a 6 1
2: 3 a 6 2
3: 5 d 7 2
Jeśli chcesz f_id
'S dla wszystkich kombinacji airport
& thisTime
gdzie DT$thisTime
jest niższa niż DT_LU$thisTime
, można to osiągnąć poprzez utworzenie nowej zmiennej (lub zastąpienie istniejącej thisTime
) za pomocą funkcji ceiling
. Przykład, w którym tworzę nowy zmienna thisTime2
a następnie wykonaj normalne połączenie z DT_LU
:
DT[, thisTime2 := ceiling(thisTime)]
setkey(DT, airport, thisTime2)[DT_LU, nomatch=0]
Co daje:
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
Zastosowane do podanych danych:
> 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
Jeśli chcesz dołączyć al przyszłe wartości zamiast tylko pierwszej, potrzebujesz nieco innego podejścia, dla którego będziesz potrzebował funkcjonalności i.col
(która nie jest jeszcze udokumentowana):
1: najpierw ustaw klucz tylko na kolumny airport
:
setkey(DT, airport)
setkey(DT_LU, airport)
2: użyj i.col
funkcjonalność (która nie jest jeszcze udokumentowana) w j
, aby uzyskać to, co chcesz w następujący sposób:
DT1 <- DT_LU[DT, .(tid = i.t_id,
tTime = i.thisTime,
fTime = thisTime[i.thisTime < thisTime],
fid = f_id[i.thisTime < thisTime]),
by=.EACHI]
To daje:
> 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
Niektóre wyjaśnienia: w przypadku łączenia dwóch tabel danych, w których używane są te same nazwy kolumn, można odnieść się do kolumn z datatable w i
, poprzedzając nazwy kolumn i.
. Teraz Można porównać thisTime
z DT
z thisTime
z DT_LU
. Z by = .EACHI
zapewniasz, że wszystkie kombinacje dla z warunkiem są zawarte w wynikowym datatable.
Alternatywnie, można osiągnąć to samo z:
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]
Co daje ten sam wynik:
> identical(DT1, DT2)
[1] TRUE
Jeśli chcesz zawrzeć przyszłe wartości tylko w określonej granicy, możesz użyć:
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]
Co daje:
> 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
Kiedy porównasz to z poprzednim wynikiem, zobaczysz, że teraz wiersze 3, 6, 9, 10 i 12 zostały usunięte.
Dane:
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"))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-22 07:28:27