2013-08-04 17 views
11
> library(data.table) 
> A <- data.table(x = c(1,1,2,2), y = c(1,2,1,2), v = c(0.1,0.2,0.3,0.4)) 
> A 
    x y v 
1: 1 1 0.1 
2: 1 2 0.2 
3: 2 1 0.3 
4: 2 2 0.4 
> B <- dcast(A, x~y) 
Using v as value column: use value.var to override. 
> B 
    x 1 2 
1 1 0.1 0.2 
2 2 0.3 0.4 

Wygląda na to, że mogę przekształcić tabelę data.table z długiej na szeroką za pomocą f.x. dcast pakietu reshape2. Ale data.table przychodzi wraz z przeciążonym operatorem-uchwytem oferującym parametry takie jak "by" i "grupa", które sprawiają, że zastanawiam się, czy można to osiągnąć za pomocą tego (do konkretnej funkcji data.table)?Przekształcanie długiej struktury danych.tabeli w szeroką strukturę za pomocą funkcji data.table?

Tylko jeden losowy przykład z podręcznika:

DT[,lapply(.SD,sum),by=x] 

To wygląda super - ale nie w pełni zrozumieć jeszcze wykorzystanie.

Ja ani nie znalazłem na to sposobu, ani przykładu, więc może to po prostu niemożliwe, może nawet nie powinno tak być - tak, zdecydowane "nie, nie jest możliwe, ponieważ ..." jest oczywiście również poprawna odpowiedź.

+0

Zobacz [tutaj] (http://stackoverflow.com/questions/15510566/nested-if-else-statements-over-a-umber-of-columns/15511689?noredirect=1#comment21968080_15511689). – Metrics

+0

Niestety, nie rozumiem, w jaki sposób ma to związek z moim pytaniem. Należy również pamiętać, że kategorie kolumn B są dynamicznie zależne od A, więc liczba wartości "y" może różnić się w zależności od przypadku. – Raffael

Odpowiedz

15

Wybiorę przykład z nierównych grupach, dzięki czemu łatwiej jest zilustrować za ogólnym przypadku:

A <- data.table(x=c(1,1,1,2,2), y=c(1,2,3,1,2), v=(1:5)/5) 
> A 
    x y v 
1: 1 1 0.2 
2: 1 2 0.4 
3: 1 3 0.6 
4: 2 1 0.8 
5: 2 2 1.0 

Pierwszym krokiem jest aby liczba elementów/wpisów dla każdej grupy "x" była taka sama. Tutaj dla x = 1 są 3 wartości y, ale tylko 2 dla x = 2. Tak więc najpierw musimy to naprawić z NA dla x = 2, y = 3.

setkey(A, x, y) 
A[CJ(unique(x), unique(y))] 

Teraz, aby dostać się do szerokiego formatu, powinniśmy grupa przez „X” i używać as.list na v następująco:

out <- A[CJ(unique(x), unique(y))][, as.list(v), by=x] 
    x V1 V2 V3 
1: 1 0.2 0.4 0.6 
2: 2 0.8 1.0 NA 

Teraz można ustawić nazwy przekształconego kolumn za pomocą odniesienia z setnames następująco:

setnames(out, c("x", as.character(unique(A$y))) 

    x 1 2 3 
1: 1 0.2 0.4 0.6 
2: 2 0.8 1.0 NA 
+0

W rzeczywistości twoje pierwsze rozwiązanie nie jest podane w twoim poście. Tak więc zachowam to z powodów akademickich! Wielkie dzięki za wysiłek! – Raffael

+0

Pierwsze rozwiązanie działa, gdy istnieją już równe wiersze dla każdej grupy. Lepiej ustawić nazwy kolumn raz na końcu niż ustawić je dla każdej grupy (co jest tym, co robi stare rozwiązanie). W przypadku większych danych mogą wystąpić problemy z wydajnością. – Arun

+1

Okej, to rozwiązanie, które znalazłem po przeczytaniu podręcznika od tygodni, chyba ... tak, może to być bardzo subiektywne, ale myślę, że mogę powiedzieć z pewnym słusznością, że to rozwiązanie jest dość skomplikowane i skomplikowane - nie ma co do tego wątpliwości jest to najprostsze rozwiązanie możliwe tylko przy użyciu data.table, o co prosiłem. Tak więc chciałbym się od ciebie dowiedzieć, czy ten obszar przekształcania zbiorów danych nie jest tym, za czym adres danych w rzeczywistości powinien się zajmować. Gdzie chciałbyś narysować linię dotyczącą ekonomicznego i rozsądnego użycia data.table i gdzie uciec się do dalszych narzędzi? – Raffael

2

(z kredytów dla Arun)

A[, setattr(as.list(v), 'names', y), by=x] 
+0

Mamy ofertę tutaj! – Raffael

+0

Błąd w '[.data.table' (A,, setattr (as.list (v)," names ", y), by = x): j nie jest oceniany na taką samą liczbę kolumn dla każdej grupy – skan

10

Korzystając dcast() (obecnie domyślną metodę data.table, od wersji 1.9 .5; Wcześniejsze wersje używać dcast.data.table) jak w

> dcast(A,x~y) 
Using 'v' as value column. Use 'value.var' to override 
    x 1 2 3 
1: 1 0.2 0.4 0.6 
2: 2 0.8 1.0 NA 

ta jest szybka i usuwa potrzebę setnames().

Jest to szczególnie pomocne, gdy y w powyższym przykładzie jest zmienną czynnikową z poziomami znaków - np. "Niski", "Średni", "Wysoki" - ponieważ CJ() może nie zwracać szerokich danych ze zmiennymi w takiej kolejności, jakiej oczekuje setnames(), i może się źle skończyć z błędnie oznaczonymi danymi.

+0

+1. Dziękujemy za zaktualizowanie tej odpowiedzi za pomocą 'dcast.data.table'. – Arun

Powiązane problemy