2012-07-31 14 views
26

Estoy intentando agregar columnas a mi data.table, donde los nombres son dinámicos. Además, necesito usar el argumento by al agregar estas columnas. Por ejemplo:Nombres dinámicos de columnas en 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. 

Otro intento:

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 

actualización de Mateo:

Esto ahora trabaja en v1.8.3 en I-Forge. Gracias por destacar!
Ver esta pregunta similar para nuevos ejemplos:

Assign multiple columns using data.table, by group

Respuesta

22

De data.table 1.9.4, sólo puede hacer esto:

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

Ver detalles en ?:=:

DT[i, (colvector) := val]

[...] Sintaxis AHORA PREFERIDA. Los parens son suficientes para evitar que el LHS sea un símbolo; mismo que c(colvector)


Respuesta original:

Usted fue exactamente en el camino correcto: la construcción de una expresión a ser evaluada dentro de la llamada a [.data.table es el data.table manera de hacerlo este tipo de cosas Yendo un poco más allá, ¿por qué no construir una expresión que evalúe el argumento enteroj (en lugar de solo su lado izquierdo)?

Algo como esto debe hacer el truco:

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

fantástico, gracias. Podría haber jurado que probé esa variación, pero obviamente no lo hice. ayuda muy apreciada. – Alex

+0

+1 Se agregó un enlace a esta pregunta a [FR # 2120] (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2120&group_id=240&atid=978). Parece estar subiendo bastante. –

15

expresión se puede construir con bquote.

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

Mucho mejor que hacer "data.tabling dinámico" – Juancentro

+0

Gran respuesta, enfoque muy útil y flexible. +1! – marbel

Cuestiones relacionadas