2010-07-15 4 views
7

Ich möchte das data.table-Paket in R verwenden, um Aggregationen dynamisch zu generieren, aber ich stehe auf einen Fehler. Belassen Sie my.dt vom Typ data.table.data.table und "von muss ausgewertet werden, um zu listen" Fehler

sex <- c("M","F","M","F") 
age <- c(19, 23, 26, 21) 
dependent.variable <- c(1400, 1500, 1250, 1100) 
my.dt <- data.table(sex, age, dependent.variable) 
grouping.vars <- c("sex", "age") 
for (i in 1:2) { 
    my.dt[,sum(dependent.variable), by=grouping.vars[i]] 
} 

Wenn ich dies ausführen, bekomme ich Fehler:

Error in `[.data.table`(my.dt, , sum(dependent.variable), by = grouping.vars[i] : 
    by must evaluate to list 

Doch die folgenden Werke ohne Fehler:

my.dt[,sum(dependent.variable), by=sex] 

ich sehen, warum der Fehler auftritt, aber ich sehe nicht, wie man einen Vektor mit dem Parameter by verwendet.

+0

Sie haben zwei "grouping.vars", die aber von 1: 5 iterieren. Fehle ich da etwas? – Shane

+1

Auch in Ihrem Arbeitsbeispiel ist Sex ein Objekt, während es in Ihrer fehlerhaften Version ein Charakter ist. – Shane

+0

Hey Shane, sorry, repariere es. Sollte 2 nicht 5 sein. Das ist mir nicht klar, es scheint, dass Sex ein Objekt ist (??). –

Antwort

4

habe ich zwei Änderungen an den ursprünglichen Code:

sex <- c("M","F","M","F") 
age <- c(19, 23, 26, 21) 

age<-as.factor(age) 

dependent.variable <- c(1400, 1500, 1250, 1100) 
my.dt <- data.table(sex, age, dependent.variable) 

for (a in 1:2){ 
print(my.dt[,sum(dependent.variable), by=list(sex,age)[a]]) 
} 

Numerische Vektor age sollte in Faktoren gezwungen werden. Als by Parameter, verwenden Sie nicht Zitat für Spaltennamen, sondern gruppieren sie in Liste (...). Zumindest hat der Autor das vorgeschlagen.

+0

Das ist interessant, und das Design hinter dem "by" scheint ein bisschen widerspenstig, aber dein Code funktioniert meistens. Nur ein kleines Problem (geringfügig und einfach zu beheben, indem nur Namen in der Schleife vergeben werden), die Spaltennamen werden nicht aktualisiert. Für variable Geschlecht, Namen sind: Geschlecht V1 Für veränderliches Alter, Namen sind: Geschlecht V1 –

5

[UPDATE] 2 Jahre nach der Frage gestellt wurde ...

Auf den Code in der Frage läuft, data.table jetzt hilfreicher ist und gibt diese (mit 1.8.2):

Error in `[.data.table`(my.dt, , sum(dependent.variable), by = grouping.vars[i]) : 
    'by' appears to evaluate to column names but isn't c() or key(). Use by=list(...) 
    if you can. Otherwise, by=eval(grouping.vars[i]) should work. This is for efficiency 
    so data.table can detect which columns are needed. 

und im Anschluss an die Beratung im zweiten Satz Fehler:

my.dt[,sum(dependent.variable), by=eval(grouping.vars[i])] 
    sex V1 
1: M 2650 
2: F 2600 



Alte Antwort vom Juli 2010 (by kann jetzt double und character, obwohl sein):

Strictly die by Bedürfnisse zu sprechen, um eine Liste von Vektoren mit je Speichermodus integer zu bewerten, though. So könnte der numerische Vektor age auch zu Ganzzahl unter Verwendung as.integer() gezwungen werden. Dies liegt daran, dass data.table eine Radix-Sortierung verwendet (sehr schnell), aber der Radix-Algorithmus ist speziell für ganze Zahlen (siehe Wikipedia-Eintrag für 'radix sort'). Integer-Speicher für Schlüsselspalten und ad hoc by ist einer der Gründe, data.table ist schnell. Ein Faktor ist natürlich ein Ganzzahl-Lookup für eindeutige Strings.

Die Idee hinter by ist ein list() von Ausdrücken ist, dass Sie nicht auf Spaltennamen beschränkt sind. Es ist üblich, Ausdrücke von Spaltennamen direkt in by zu schreiben. Eine allgemeine ist es, nach Monat zu aggregieren; zum Beispiel:

DT[,sum(col1), by=list(region,month(datecol))] 

oder eine sehr schnelle Art und Weise zu einer Gruppe von yearmonth ist durch ein nicht Epoche basierend Datum, wie yyyymmddL, wie in einige der Beispiele in der Verpackung, so gesehen:

DT[,sum(col1), by=list(region,month=datecol%/%100L)] 

Beachten Sie, wie Sie die Spalten in der Liste() so benennen können.

definieren und komplexe Gruppierung Ausdrücke wiederverwenden:

e = quote(list(region,month(datecol))) 
DT[,sum(col1),by=eval(e)] 
DT[,sum(col2*col3/col4),by=eval(e)] 

Oder wenn Sie die by Ausdrücke jedes Mal neu zu bewerten, nicht möchten, können Sie das Ergebnis einmal und wiederverwenden das Ergebnis für Effizienz sparen; wenn die by Ausdrücke selbst eine lange Zeit in Anspruch nehmen zu berechnen/zuweisen, oder Sie müssen es viele Male wiederverwendet werden:

byval = DT[,list(region,month(datecol))] 
DT[,sum(col1),by=byval] 
DT[,sum(col2*col3/col4),by=byval] 

Bitte sehen http://datatable.r-forge.r-project.org/ für die neuesten Informationen und Status. Eine neue Präsentation wird bald da sein und hoffen, bald auch v1.5 für CRAN zu veröffentlichen. Dies enthält einige Fehlerbehebungen und neue Funktionen, die in der NEWS-Datei aufgeführt sind. Die datatable-help-Liste enthält ungefähr 30-40 Beiträge pro Monat, was ebenfalls von Interesse sein könnte.

Verwandte Themen