To jest trochę filozoficzne pytanie dotyczące składni łączenia danych. Znajduję coraz więcej zastosowań dla danych. Tabele, ale wciąż się uczę ...
Format sprzężenia X[Y]
dla data.tables jest bardzo zwięzły, poręczny i wydajny, ale o ile wiem, obsługuje tylko sprzężenia wewnętrzne i prawe sprzężenia zewnętrzne. Aby uzyskać lewe lub pełne sprzężenie zewnętrzne, muszę użyć merge
:
X[Y, nomatch = NA]
- wszystkie wiersze w Y - prawe sprzężenie zewnętrzne (domyślne)X[Y, nomatch = 0]
- tylko wiersze z dopasowaniami w X i Y - sprzężenie wewnętrznemerge(X, Y, all = TRUE)
- wszystkie rzędy od X i Y - pełne połączenie zewnętrznemerge(X, Y, all.x = TRUE)
- wszystkie wiersze w X - lewe połączenie zewnętrzne
Wydaje mi się, że przydałoby się, gdyby X[Y]
format złączeń obsługiwał wszystkie 4 typy złączeń. Czy jest jakiś powód, dla którego obsługiwane są tylko dwa typy złączeń?
Dla mnie wartości parametrów nomatch = 0
i nomatch = NA
nie są zbyt intuicyjne dla wykonywanych czynności. Łatwiej jest mi zrozumieć i zapamiętać merge
składnię: all = TRUE
, all.x = TRUE
i all.y = TRUE
. Ponieważ X[Y]
operacja przypomina merge
znacznie więcej niż match
, dlaczego nie użyć merge
składni dla złączeń zamiast parametru match
funkcji nomatch
?
Oto przykłady kodu 4 typów złączeń:
# sample X and Y data.tables
library(data.table)
X <- data.table(t = 1:4, a = (1:4)^2)
setkey(X, t)
X
# t a
# 1: 1 1
# 2: 2 4
# 3: 3 9
# 4: 4 16
Y <- data.table(t = 3:6, b = (3:6)^2)
setkey(Y, t)
Y
# t b
# 1: 3 9
# 2: 4 16
# 3: 5 25
# 4: 6 36
# all rows from Y - right outer join
X[Y] # default
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
X[Y, nomatch = NA] # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
merge(X, Y, by = "t", all.y = TRUE) # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
identical(X[Y], merge(X, Y, by = "t", all.y = TRUE))
# [1] TRUE
# only rows in both X and Y - inner join
X[Y, nomatch = 0]
# t a b
# 1: 3 9 9
# 2: 4 16 16
merge(X, Y, by = "t") # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
merge(X, Y, by = "t", all = FALSE) # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
identical( X[Y, nomatch = 0], merge(X, Y, by = "t", all = FALSE) )
# [1] TRUE
# all rows from X - left outer join
merge(X, Y, by = "t", all.x = TRUE)
# t a b
# 1: 1 1 NA
# 2: 2 4 NA
# 3: 3 9 9
# 4: 4 16 16
# all rows from both X and Y - full outer join
merge(X, Y, by = "t", all = TRUE)
# t a b
# 1: 1 1 NA
# 2: 2 4 NA
# 3: 3 9 9
# 4: 4 16 16
# 5: 5 NA 25
# 6: 6 NA 36
Aktualizacja: data.table v1.9.6 wprowadziła on=
składnię, która umożliwia łączenia ad hoc w polach innych niż klucz podstawowy. odpowiedź jangoreckiego na pytanie Jak łączyć (scalać) ramki danych (wewnętrzne, zewnętrzne, lewe, prawe)? zawiera kilka przykładów dodatkowych typów złączeń, które może obsługiwać data.table.
unique()
podejście poniżej dla pełnego sprzężenia jest lepsze rbind(Y[X],X[Y])
, ponieważ rbind wymagałoby skopiowania tabeli. Czy to prawda?
unique(c(unique(X[,t]), unique(Y[,t]))
- powinno to być bardziej wydajnepamięć, ponieważ łączy tylko dwie listy, które będą mniejsze lub równe liczbie wierszy w X i Y .
Y[X]
, jeśli chcesz lewo sprzężenie zewnętrzne odX[Y]
irbind(Y[X],X[Y])
jeśli chcesz pełne sprzężenie zewnętrzne