Wie gruppiere ich data.table nach mehreren Spalten?

70

Ich verwende das data.tablePaket, um eine zusammenfassende Statistiksammlung für einen Datensatz zu beschleunigen.

Ich bin gespannt, ob es eine Möglichkeit gibt, nach mehr als einer Spalte zu gruppieren. Meine Daten sehen folgendermaßen aus:

  purchaseAmt        adShown        url
   15.54            00001         150000001
    4.82            00002         150000001
  157.99            05005         776300044
   ...               ...            ...

Ich kann so etwas machen:

adShownMedian <- df1[,median(purchaseAmt),by="adShown"]

um den Median jeder Anzeige zu erhalten. Wie würde ich etwas tun, das kombiniert adShownund url?

Ich habe das versucht:

adShownMedian <- df1[,median(purchaseAmt),by=c("adShown","url")]

aber kein Glück.

Irgendwelche Vorschläge?

screechOwl
quelle
1
Welche Version von verwenden data.tableSie? Ich bin mir ziemlich sicher, dass Sie mit Version 1.8.2 einen Zeichenvektor mit Spaltennamen an das byArgument übergeben können.
BenBarnes
3
Genau. Entweder eine (sehr) alte Version von data.table oder ein anderer Fehler. ?data.tablesagt: " by- Ein einzelner nicht zitierter Spaltenname, eine Liste () von Ausdrücken von Spaltennamen, eine einzelne Zeichenfolge mit durch Kommas getrennten Spaltennamen oder ein Zeichenvektor von Spaltennamen." Also c("adShown","url")sollte es gut sein, oder "adShown,url", oder list(adShown,url).
Matt Dowle
@ BenBarnes: Guter Fang, ich bin immer noch auf 1.8.
ScreechOwl

Antworten:

92

Verwenden Sie by=list(adShown,url)anstelle vonby=c("adShown","url")

Beispiel:

set.seed(007) 
DF <- data.frame(X=1:20, Y=sample(c(0,1), 20, TRUE), Z=sample(0:5, 20, TRUE))

library(data.table)
DT <- data.table(DF)
DT[, Mean:=mean(X), by=list(Y, Z)]


     X Y Z      Mean
 1:  1 1 3  1.000000
 2:  2 0 1  9.333333
 3:  3 0 5  7.400000
 4:  4 0 5  7.400000
 5:  5 0 5  7.400000
 6:  6 1 0  6.000000
 7:  7 0 3  7.000000
 8:  8 1 2 12.500000
 9:  9 0 5  7.400000
10: 10 0 2 15.000000
11: 11 0 4 14.500000
12: 12 0 1  9.333333
13: 13 1 1 13.000000
14: 14 0 1  9.333333
15: 15 0 2 15.000000
16: 16 0 5  7.400000
17: 17 1 2 12.500000
18: 18 0 4 14.500000
19: 19 1 5 19.000000
20: 20 0 2 15.000000
Jilber Urbina
quelle
7
Sollte by=c("adShown","url")aber auch in Ordnung sein. +1 sowieso.
Matt Dowle
9
Ist es möglich , die aggregiert zeigen nur Y, Zund MeanSpalten, so wie aggregatefunktioniert?
Kahlo
3
Soweit ich das beurteilen kann, müssen listSie die Namen nicht wie bei Vektoren zitieren c(), was irgendwie interessant ist.
PatrickT
1
Wenn Sie also nach Y und Z gruppieren, sollte es in DT nur einmal angezeigt werden. Zum Beispiel sollten Sie nur eine Zeile haben, wenn Y = 0, Z = 5 und Mittelwert = 7,40. Sie haben jedoch fünf davon in Ihrem DT. Vermisse ich hier etwas?
Muhsin Zahid Ugur
3
@PatrickT Danke für den Tipp! Mit diesem Trick können Sie auch nach Ausdruck gruppieren, was sehr praktisch ist.
random_forest_fanatic
5

So fügen Sie die Antwort von Jilber Urbina hinzu und adressieren den Kahlo-Kommentar:
Wenn Sie eine einzelne Zeile für jede Y-Z-Kombination mit den aggregierten Werten erhalten möchten, können Sie dies tun

DT[, .(X=mean(X)), by=list(Y, Z)]

das ist das gleiche wie zu tun

DT[, .(X=mean(X)), by=.(Y, Z)] 
# or
DT[, .(X=mean(X)), by=c('Y','Z')]
# or specify column names in vector
names = c('Y','Z')
DT[, .(X=mean(X)), by=names] 

(data.table Version 1.12.6)

Fernando.-
quelle