2012-03-26 16 views
5

Celem jest utworzenie wskaźników dla zmiennej czynnik/łańcuch w ramce danych. Ta ramka danych ma> 2 mm wierszy, a R na windows, nie mam możliwości użycia plyr z .parallel = T. Więc biorę trasę "dziel i rządź" z plyr i reshape2.Generowanie wskaźników w dużych ramkach danych

Running stopienia i odlewanych zabraknie pamięci, a przy użyciu

ddply(idata.frame(items) , c("ID") , function(x){ 
     ( colSums(model.matrix(~ x$element - 1)) > 0 ) 
} , .progress="text")  

lub

ddply(idata.frame(items) , c("ID") , function(x){ 
      ( elements %in% x$element ) 
    } , .progress="text") 

ma potrwać. Najszybszym podejściem jest wezwanie do zastosowania poniżej. Czy widzisz sposób na przyspieszenie tego? Instrukcja% in% działa szybciej niż wywołanie model.matrix. Dzięki.

set.seed(123) 

dd <- data.frame(
    id = sample(1:5, size=10 , replace=T) , 
    prd = letters[sample(1:5, size=10 , replace=T)] 
) 

prds <- unique(dd$prd) 

tapply(dd$prd , dd$id , function(x) prds %in% x) 
+0

Jestem zdezorientowany twoim przykładem. Dzielisz 'dd $ prd' przez' dd $ id', następnie pytasz, które wartości 'prds' są reprezentowane w każdym id - ale' prds' nie jest posortowane (!) Czy chcesz 'prds <- sort (unique (dd $ prd)) '(co miałoby dla mnie dużo więcej sensu ...)? –

+0

Dopóki wskaźniki (logiczne) odpowiadające elementom dostępnym w programach PRDS mają tę samą kolejność identyfikatorów, nie ma znaczenia, w jaki sposób są sortowane. –

+0

OK. Zobacz moje inne pytanie, w mojej odpowiedzi poniżej ... –

Odpowiedz

4

tego problemu, opakowania bigmemory i bigtabulate może być twoimi przyjaciółmi. Tu jest nieco bardziej ambitny przykład:

library(bigmemory) 
library(bigtabulate) 

set.seed(123) 

dd <- data.frame(
    id = sample(1:15, size=2e6 , replace=T), 
    prd = letters[sample(1:15, size=2e6 , replace=T)] 
) 

prds <- unique(dd$prd) 

benchmark(
bigtable(dd,c(1,2))>0, 
table(dd[,1],dd[,2])>0, 
xtabs(~id+prd,data=dd)>0, 
tapply(dd$prd , dd$id , function(x) prds %in% x) 
) 

a wyniki analizy porównawczej (uczę się nowych rzeczy cały czas):

          test replications elapsed relative user.self sys.self user.child sys.child 
1      bigtable(dd, c(1, 2)) > 0   100 54.401 1.000000 51.759 3.817   0   0 
2     table(dd[, 1], dd[, 2]) > 0   100 112.361 2.065422 107.526 6.614   0   0 
4 tapply(dd$prd, dd$id, function(x) prds %in% x)   100 178.308 3.277660 166.544 13.275   0   0 
3    xtabs(~id + prd, data = dd) > 0   100 229.435 4.217478 217.014 16.660   0   0 

I to pokazuje bigtable wygranej przez znaczną kwotę. Wyniki są prawie takie, że wszystkie prdki są we wszystkich identyfikatorach, ale zobacz ?bigtable, aby uzyskać szczegółowe informacje na temat formatu wyników.

+0

Dziękuję bardzo. –

+0

Bieg właśnie zakończony (przy użyciu bigtable) na rzeczywistym zestawie danych (!). –

1

Korzystanie z funkcji %in% wydaje mi się odwrotne. A jeśli chcesz uzyskać wynik prawdziwy/fałszywy dla każdego rzędu danych, powinieneś użyć% w% jako operacji wektorowej lub ave. Chociaż nie jest to potrzebne, możesz go użyć, jeśli istnieje bardziej złożona funkcja, którą należy zastosować do każdego elementu.

set.seed(123) 

dd <- data.frame(
    id = sample(1:5, size=10 , replace=T) , 
    prd = letters[sample(1:5, size=10 , replace=T)] 
) 

prds <- unique(dd$prd) 
target.prds <- prds[1:2] 
dd$prd.in.trgt <- with(dd, prd %in% target.prds) 
+0

Będzie tyle wskaźników, ile jest "PRDS" (lub 'target.prds'):' c (1,2,3)% w% c (1) 'będzie wskazywać, że 1 jest w tym rekordzie, ale ani 2 ani 3. –

+0

Nie możesz po prostu przedefiniować% w%, aby być czymś, czym nie jest. I ramka danych potrzebuje wszystkich elementów, aby mieć regularną liczbę wpisów na wiersz. Musisz użyć struktury danych, która zawiera numer zmiennej, jeśli "trafienia", ... albo logiczna macierz wartości PRAWDA i FAŁSZ, albo lista. –

+0

Nie jestem pewien, czy rozumiem, co mówisz. Wywołanie "% w%" zawsze zwróci tę samą liczbę logicznych. Zaczynałem od 'function (x) unique (x $ prd)' w wywołaniu 'tapply', które spowodowałoby powstanie nierównej tablicy. –

2

można powiedzieć trochę więcej jak problem będzie skalować pod względem liczby poziomów, numery identyfikatorów itd (jeśli trzymać liczby poziomów stałych, a następnie na tyle osób matrycy Ci wskaźnik "obliczenia będą zbliżać się do wszystkich PRAWDZIWYCH/wszystkich 1 ...)? Spodziewałem się, że xtabs byłoby szybciej, ale to nie jest dla przykładu tej wielkości ...

library(rbenchmark) 
benchmark(
      tapply(dd$prd , dd$id , function(x) prds %in% x), 
      xtabs(~id+prd,data=dd)>0) 

    test  replications elapsed relative 
1 tapply(...)    100 0.053 1.000000 
2 xtabs(...) > 0   100 0.120 2.264151 
+0

Istnieje 13,5 miliona pozycji (na 780 000 identyfikatorów, więc wiele pozycji na identyfikatory).W prd jest 83 różnych elementów. Dziękuję za zwrócenie mojej uwagi na rollchmark. –

Powiązane problemy