2012-12-20 12 views
8

Ich bin auf der Suche nach Mustern für die Manipulation data.table Objekte, deren Struktur ähnelt der von Datenrahmen mit melt aus dem reshape2 Paket erstellt. Ich beschäftige mich mit Datentabellen mit Millionen von Zeilen. Leistung ist entscheidend. Die verallgemeinerte Form der Frage ist, ob es eine Möglichkeit gibt, die Gruppierung basierend auf einer Teilmenge von Werten in einer Spalte durchzuführen und das Ergebnis der Gruppierungsoperation eine oder mehrere neue Spalten zu erzeugen.Schnell geschmolzen data.table Operationen

könnte eine spezifische Form der Frage sein, wie data.table zu verwenden, um das Äquivalent zu erreichen, was dcast tut in den folgenden:

input <- data.table(
    id=c(1, 1, 1, 2, 2, 2, 3, 3, 3, 3), 
    variable=c('x', 'y', 'y', 'x', 'y', 'y', 'x', 'x', 'y', 'other'), 
    value=c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) 
dcast(input, 
    id ~ variable, sum, 
    subset=.(variable %in% c('x', 'y'))) 

dessen Ausgang

id x y 
1 1 1 5 
2 2 4 11 
3 3 15 9 
+0

ich bin verwirrt , sorry - die Funktion dcast() funktioniert ohne die as.data.frame() - Bedingung. Versuchen Sie, dies zu erreichen, ohne das plyr-Paket zu verwenden? –

+0

@AnthonyDamico Ja, ich möchte das ohne 'dcast' machen, was in' reshape2' steht. Ich habe das as.data.frame() entfernt - danke, dass du das herausgebracht hast. – Sim

Antwort

8

Schnell ungetestet Antwort: scheint, wie Sie für by-ohne-by, aka suchen grouping- by-i:

setkey(input,variable) 
input[c("x","y"),sum(value)] 

ist dies wie ein schnell in SQL DAR. j wird für jede Zeile von i ausgewertet. Mit anderen Worten, die oben das gleiche Ergebnis, aber viel schneller als:

input[,sum(value),keyby=variable][c("x","y")] 

die letztere Teilmengen und evals für alle Gruppen (verschwenderisch), bevor nur die Gruppen von Interesse auswählen. Die erste (by-by-by) geht direkt zu der Untergruppe von Gruppen.

Die Gruppenergebnisse werden wie immer im langen Format zurückgegeben. Die anschließende Umformung auf die (relativ kleinen) aggregierten Daten sollte jedoch relativ zeitnah erfolgen. Das ist sowieso das Denken.

Die erste setkey(input,variable) könnte beißen, wenn input eine Menge Spalten hat, die nicht von Interesse sind. Wenn ja, könnte es sich lohnen, subsetting die Spalten benötigt:

DT = setkey(input[,c("variable","value"),with=FALSE], variable) 
DT[c("x","y"),sum(value)] 

In Zukunft, wenn sekundäre Schlüssel implementiert, wäre einfacher:

set2key(input,variable)    # add a secondary key 
input[c("x","y"),sum(value),key=2] # syntax speculative 

Zur Gruppe von id auch:

setkey(input,variable) 
input[c("x","y"),sum(value),by='variable,id'] 

und einschließlich id in den Schlüssel könnte setkey Kosten sind abhängig von Ihren Daten:

Wenn Sie ein by-without-by mit by kombinieren, wie oben, dann funktioniert das by-without-by genau wie eine Untermenge; d.h.j wird nur für jede Zeile von i ausgeführt, wenn durch fehlt (daher der Name by-ohne-by). Sie müssen also variable erneut in die by wie oben gezeigt einfügen.

Alternativ sollte folgende Gruppe von id über die Vereinigung von „x“ und „y“ statt (aber die oben ist, was Sie in der Frage gestellt, iiuc):

input[c("x","y"),sum(value),by=id] 
+0

Sekundärschlüssel wären sehr hilfreich. Alternativ, eine Möglichkeit, "Variationen" durch Referenz mit verschiedenen Schlüsseln zu erstellen. Das Muster, das ich immer wieder entdecke, muss den Schlüssel mehrmals für verschiedene Operationen mit derselben by-Klausel, aber verschiedenen select-Klauseln ändern und dann das Endergebnis manuell aus den Datentabellen jeder Operation zusammensetzen. – Sim

3
> setkey(input, "id") 
> input[ , list(sum(value)), by=id] 
    id V1 
1: 1 6 
2: 2 15 
3: 3 34 

> input[ variable %in% c("x", "y"), list(sum(value)), by=id] 
    id V1 
1: 1 6 
2: 2 15 
3: 3 24 

ist Die letzte:

> input[ variable %in% c("x", "y"), list(sum(value)), by=list(id, variable)] 
    id variable V1 
1: 1  x 1 
2: 1  y 5 
3: 2  x 4 
4: 2  y 11 
5: 3  x 15 
6: 3  y 9 
+0

Dies führt 'sum' für alle Variablen im Gegensatz zu nur' x' und 'y'. In meinem Fall gibt es Hunderte von verschiedenen Variablen, also brauche ich eine Subsetting-Klausel. Ich würde es lieben, das nicht zu tun, indem ich eine ganze temporäre Datentabelle erstelle. – Sim

+1

das ist näher, aber immer noch nicht perfekt keycols <- c ("id", "variable"); setkeyv (Eingabe, Keycols); Eingabe [Eingabe $ Variable% in% c ('x', 'y'), Liste (Summe (Wert)), mit = Schlüsselzahlen] –

+0

@Sim: Ich habe Ihnen nur Optionen gezeigt. Die letzte ist alles, was Sie brauchen, und es erstellt keine Zwischentabelle. –

2

Ich bin nicht sicher, ob dies der beste Weg ist, aber man kann versuchen:

input[, list(x = sum(value[variable == "x"]), 
      y = sum(value[variable == "y"])), by = "id"] 
# id x y 
# 1: 1 1 5 
# 2: 2 4 11 
# 3: 3 15 9 
+0

Erstellt das nicht zwei temporäre Vektoren für die 'variable' Gleichheit für jeden Wert von 'id'? – Sim