¿Cómo usar data.table dentro de una función?

As a minimal working example, for instance, I want to be able to dynamically pass expressions to a data.table object to create new columns or modify existing ones:

dt <- data.table(x = 1, y = 2)
dynamicDT <- function(...) {
    dt[, list(...)]
}
dynamicDT(z = x + y)

Yo estaba esperando:

   z
1: 3

but instead, I get the error:

Error in eval(expr, envir, enclos) : object 'x' not found 

Entonces, ¿cómo puedo arreglar esto?

Intentos:

He visto esta publicación, que sugiere utilizar quote or substitute, pero

> dynamicDT(z = quote(x + y))
Error in `rownames<-`(`*tmp*`, value = paste(format(rn, right = TRUE),  : 
  length of 'dimnames' [1] not equal to array extent

or

> dynamicDT <- function(...) {
+     dt[, list(substitute(...))]
+ }
> dynamicDT(z = x + y)
Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L,  : 
  first argument must be atomic

haven't worked for me.

preguntado el 28 de mayo de 14 a las 12:05

You won't get that desired output if you will use list. If you function will work, the output will be z 1: 3. Necesitas usar := -

@DavidArenburg. Thanks for pointing that out - was an oversight when writing. Fixed now. -

I actually wrote an answer for your original desired output, do you still need it -

Sure - thanks David. Shouldn't be too hard to tweak the final output. The important bit is how you manage to pass expressions to be evaluated in context of the data.table rather than .GlobalEnv. -

See my edit re multiple variables -

2 Respuestas

This should be a better alternative to David's answer:

dynamicDT <- function(...) {
 dt[, eval(substitute(...))]
}

dynamicDT(z := x + y)
#   x y z
#1: 1 2 3

contestado el 28 de mayo de 14 a las 12:05

(+1) Nice one @Roland, certainly better - David Aremburgo

Thanks - can this handle multiple arguments such as dynamicDT(a := x + y, b := x - y)? - mchen

It still has to be correct data.table syntax. See David's answer for the syntax. - Roland

Necesitarás usar eval(parse(text = )) combinación. parse will transform the string into an expression, while eval will evaluate it.

library(data.table)
dt <- data.table(x = 1, y = 2)
dynamicDT <- function(temp = "") {
  dt[, eval(parse(text = temp))]
}

In order to get your previous desired output

dynamicDT("z := x + y")
##    x y z
## 1: 1 2 3

In order to get your current desired output

dynamicDT("z = x + y")
## [1] 3

In order to parse multiple arguments you can do

dynamicDT('c("a","b") := list(x + y, x - y)')

##   x y a  b
##1: 1 2 3 -1

contestado el 28 de mayo de 14 a las 13:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.