2013-01-02 15 views
6

że dwa data.tables DT i l:wielokrotne wejścia/łączy się z data.tables

> DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9,key="x") 
> L=data.table(yv=c(1L:8L,12L),lu=c(letters[8:1],letters[12]),key="yv") 

> DT 
    x y v 
1: a 1 1 
2: a 3 2 
3: a 6 3 
4: b 1 4 
5: b 3 5 
6: b 6 6 
7: c 1 7 
8: c 3 8 
9: c 6 9 

> L 
    yv lu 
1: 1 h 
2: 2 g 
3: 3 f 
4: 4 e 
5: 5 d 
6: 6 c 
7: 7 b 
8: 8 a 
9: 12 l 

Chciałbym niezależnie wyszukać odpowiednią wartość lu z L na kolumnie Y i V kolumny w DT. Następującą składnię daje poprawny wynik, ale jest kłopotliwe w celu wytworzenia i zrozumieć na stronie dalszej:

> L[setkey(L[setkey(DT,y)],v)][,list(x,y=yv.1,v=yv,lu.1=lu.1,lu.2=lu)] 
    x y v lu.1 lu.2 
1: a 1 1 h h 
2: a 2 3 g f 
3: a 3 6 f c 
4: b 4 1 e h 
5: b 5 3 d f 
6: b 6 6 c c 
7: c 7 1 b h 
8: c 8 3 a f 
9: c 9 6 NA c 

(Edycja: oryginalna etat L[setkey(L[setkey(DT,y)],v)][,list(x,y=yv,v=yv.1,lu.1=lu,lu.2=lu.1)] powyżej, które nieprawidłowo miesza się Y i V kolumny i wyglądał w górę wartości)

W SQL byłoby to prosty/prosty.

SELECT DT.*, L1.lu AS lu1, L2.lu AS lu2 
FROM DT 
LEFT JOIN L AS L1 ON DT.y = L1.yv 
LEFT JOIN L AS L2 ON DT.v = L2.yv 

Czy jest bardziej elegancki sposób na wykorzystanie data.table do wykonywania wielu łączy? Zauważ, że w tym przykładzie dwukrotnie dołączam do jednej tabeli do innej tabeli, ale jestem również zainteresowany dołączeniem jednej tabeli do wielu różnych tabel.

Odpowiedz

6

Świetne pytanie. Jedna sztuczka polega na tym, że i nie musi być kluczowany. Tylko x musi być kluczowany.

Możliwe, że istnieją lepsze sposoby. Jak o tym:

> cbind(L[DT[,list(y)]], L[DT[,list(v)]], DT) 
    yv lu yv lu x y v 
1: 1 h 1 h a 1 1 
2: 3 f 2 g a 3 2 
3: 6 c 3 f a 6 3 
4: 1 h 4 e b 1 4 
5: 3 f 5 d b 3 5 
6: 6 c 6 c b 6 6 
7: 1 h 7 b c 1 7 
8: 3 f 8 a c 3 8 
9: 6 c 9 NA c 6 9 

lub, aby zilustrować, to jest ta sama:

> cbind(L[J(DT$y)], L[J(DT$v)], DT) 
    yv lu yv lu x y v 
1: 1 h 1 h a 1 1 
2: 3 f 2 g a 3 2 
3: 6 c 3 f a 6 3 
4: 1 h 4 e b 1 4 
5: 3 f 5 d b 3 5 
6: 6 c 6 c b 6 6 
7: 1 h 7 b c 1 7 
8: 3 f 8 a c 3 8 
9: 6 c 9 NA c 6 9 

merge mogą być również wykorzystywane, jeśli następujące żądanie funkcja została wprowadzona:

FR#2033 Add by.x and by.y to merge.data.table

+0

Dzięki za końcówkę cindla i szybką odpowiedź. Ta metoda jest mniej zagnieżdżona i łatwiejsza do odczytania niż moja oryginalna próba. Aby wyczyścić wynikowe nazwy kolumn, użyję czegoś takiego jak 'cbind (DT, L [J (DT $ y)] [, lista (lu.1 = lu)], L [J (DT $ v)]) [, lista (x, y, v, lu.1, lu.2 = lu)] '. Moje doświadczenie w SQL uwarunkowało mnie, że nigdy nie polegam na kolejności sortowania wierszy, więc łączenie kolumn wydaje się błędne, ale oczywiście działa w R. Potrzebuję więcej "myślenia w R". Ogromny wielbiciel twojej pracy, BTW. – dnlbrky

+0

Czy wdrożenie FR # 2033 umożliwiłoby scalenie wielu tabel? Jak rozumiem, "scalanie" jest używane dla dwóch ramek danych, a nie wielu. Widzę niektóre opcje, takie jak 'merge_all' i' merge_recurse' w przekształceniu, ale nie mogę znaleźć zbyt wielu przykładów (szczególnie z kilkoma zestawami kluczy obcych), więc nie jestem pewien, jak z nich korzystać, nawet gdyby działały w tym przykład. – dnlbrky

+0

Ogólnie w R i na data.table nie używamy tylu tabel. Czynniki są podobne do obcych kluczy w sql, a te dni, ponieważ znak jest automatycznie buforowany przez R w globalnej pamięci podręcznej, znak jest naprawdę skuteczny. Duże płaskie stoły, zdenormalizowane, są generalnie dobre. Data.table grupuje tylko kolumny, których potrzebuje, więc nie ma wady wielu kolumn, jak to jest w zapisanym w wierszu pliku sql. –