2012-07-31 14 views
26

Ich versuche, Spalten zu meinem data.table hinzuzufügen, wo die Namen dynamisch sind. Ich brauche zusätzlich das Argument by beim Hinzufügen dieser Spalten. Zum Beispiel:Dynamische Spaltennamen in data.table

test_dtb <- data.table(a = sample(1:100, 100), b = sample(1:100, 100), id = rep(1:10,10)) 
cn <- parse(text = "blah") 
test_dtb[ , eval(cn) := mean(a), by = id] 

# Error in `[.data.table`(test_dtb, , `:=`(eval(cn), mean(a)), by = id) : 
# LHS of := must be a single column name when with=TRUE. When with=FALSE the LHS may be a vector of column names or positions. 

Ein weiterer Versuch:

cn <- "blah" 
test_dtb[ , cn := mean(a), by = id, with = FALSE] 
# Error in `[.data.table`(test_dtb, , `:=`(cn, mean(a)), by = id, with = FALSE) : 'with' must be TRUE when 'by' or 'keyby' is provided 

Update von Matthew:

Dies funktioniert nun in v1.8.3 auf R-Forge. Danke für die Hervorhebung!
Sehen Sie diese ähnliche Frage für neue Beispiele:

Assign multiple columns using data.table, by group

Antwort

22

Von data.table 1.9.4, können Sie dies nur tun:

## A parenthesized symbol, `(cn)`, gets evaluated to "blah" before `:=` is carried out 
test_dtb[, (cn) := mean(a), by = id] 
head(test_dtb, 4) 
#  a b id blah 
# 1: 41 19 1 54.2 
# 2: 4 99 2 50.0 
# 3: 49 85 3 46.7 
# 4: 61 4 4 57.1 

Einzelheiten in ?:= Siehe:

DT[i, (colvector) := val]

[...] jetzt bevorzugte [...] Syntax. Die Parens sind genug, um zu verhindern, dass die LHS ein Symbol ist; gleiche wie c(colvector)


Ursprüngliche Antwort:

Sie waren auf genau dem richtigen Weg: einen Ausdruck der Konstruktion innerhalb des Anrufs zu [.data.table ausgewertet werden, ist das data.table Art und Weise zu tun so etwas. Gehen Sie nur ein bisschen weiter, warum nicht einen Ausdruck erstellen, der das ganze Argument (und nicht nur seine linke Seite) auswertet?

So etwas sollte es tun:

## Your code so far 
library(data.table) 
test_dtb <- data.table(a=sample(1:100, 100),b=sample(1:100, 100),id=rep(1:10,10)) 
cn <- "blah" 

## One solution 
expr <- parse(text = paste0(cn, ":=mean(a)")) 
test_dtb[,eval(expr), by=id] 

## Checking the result 
head(test_dtb, 4) 
#  a b id blah 
# 1: 30 26 1 38.4 
# 2: 83 82 2 47.4 
# 3: 47 66 3 39.5 
# 4: 87 23 4 65.2 
+0

fantastisch, danke. Ich hätte schwören können, dass ich diese Variante ausprobiert habe, aber offensichtlich nicht. Hilfe sehr geschätzt. – Alex

+0

+1 Ein Link zu dieser Frage wurde zu [FR # 2120] hinzugefügt (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2120&group_id=240&atid=978). Scheint ziemlich hoch zu kommen. –

15

Expression kann mit bquote konstruiert werden.

cn <- "blah" 
expr <- bquote(.(as.name(cn)):=mean(a)) 
test_dtb[,eval(expr), by=id] 
+1

Viel schöner als "dynamic data.tabling" – Juancentro

+0

Große Antwort, sehr nützliche und flexible Vorgehensweise. +1! – marbel

Verwandte Themen