2012-07-31 61 views
26

我正在嘗試向我的data.table添加列,其中名稱是動態的。另外,我需要在添加這些列時使用by參數。例如: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. 

的另一種嘗試:從馬修

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 

更新:

這現在在v1.8.3的R-僞造。感謝您的突出!
見新的實例中,這類似的問題:

Assign multiple columns using data.table, by group

回答

22

data.table 1.9.4,你可以這樣做:

## 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 

詳細?:=

DT[i, (colvector) := val]

[...] NOW PREFERRED語法。這些包具足以阻止LHS成爲一種象徵;同c(colvector)


原來的答覆:

你是在完全正確的軌道:構建表達呼叫內進行評估,以[.data.table是做data.table方式這種事情。進一步說,爲什麼不構建一個表達式,其計算結果爲整個參數(而不僅僅是其左手側)?

像這樣的東西應該做的伎倆:

## 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

太棒了,謝謝。我可以發誓我嘗試了這種變化,但顯然我沒有。非常感謝。 – Alex 2012-07-31 17:52:09

+0

+1將此問題的鏈接添加到了[FR#2120](https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2120&group_id=240&atid=978)。似乎會出現很多。 – 2012-08-09 13:26:34

15

表達可以用bquote構造。

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

比做「動態data.tabling」好得多 – Juancentro 2013-09-12 18:34:47

+0

很好的答案,非常有用和靈活的方法。 +1! – marbel 2017-04-19 15:49:57