2012-05-20 8 views
17

Tengo un pequeño problema R con data.table. Su ayuda es muy apreciada. ¿Cómo puedo hacer esto:En R data.table, ¿cómo paso los parámetros variables a una expresión?

getResult <- function(dt, expr, gby) { 
    e <- substitute(expr) 
    b <- substitute(gby) 
    return(dt[,eval(e),by=b]) 
} 

v1 <- "Sepal.Length" 
v2 <- "Species" 

dt <- data.table(iris) 
rDT <- getResult(dt, sum(v1, na.rm=TRUE), v2) 

consigo siguiente error:

Error in sum(v1, na.rm = TRUE) : invalid 'type' (character) of argument

Ahora, tanto v1 y v2 van pasando desde otro programa como variable de caracteres, así que no puedo hacer esto v1<- quote(Sepal.Length) que parece trabajo.

+9

Esto puede ponerlo en el camino correcto: 'dt [, sum (get (v1), na.rm = TRUE), by = v2]' o sugerir un enfoque alternativo si es flexible. – flodel

+0

Thx. Funcionó, ¿qué pasó? La función obtiene el objeto llamado v1. ¿Qué le hizo la función sustituta a esta expresión? ¿No hizo nada e intentó reemplazar v1 con el valor de carácter "Sepal.Length"? – user1157129

Respuesta

20

Una alternativa a flodel de respuesta en los comentarios podría ser

e <- parse(text = paste0("sum(", v1, ", na.rm = TRUE)")) 

b <- parse(text = v2) 

rDT2 <- dt[, eval(e), by = eval(b)] 

#    b V1 
# [1,]  setosa 250.3 
# [2,] versicolor 296.8 
# [3,] virginica 329.4 

EDIT:

Y para poner esto en una función,

getResult <- function(dt, expr, gby){ 
    return(dt[, eval(expr), by = eval(gby)]) 
} 

(dtR <- getResult(dt = dt, expr = e, gby = b)) 
# gives the same result as above 


EDITAR de Mateo : Hay una razón sutil por la que los métodos paste0 y eval \ quote pueden ser más rápidos que get en algunos casos, también. Una de las razones por las que la agrupación puede ser rápida es que data.table inspeccione j para ver qué columnas utiliza, y luego solo subconjuntos de esas columnas usadas (preguntas más frecuentes 1.12 y 3.1). Utiliza base::all.vars(j) para hacer eso. Al utilizar get() en j la columna que se utiliza está oculto a all.vars y data.table cae de nuevo a subconjuntos de todas las columnas en caso de que la expresión j los necesita (al igual que cuando el símbolo .SD se utiliza en j, para lo cual se añadió .SDcols de resolver) . Si todas las columnas se utilizan de todos modos, entonces no hace la diferencia, pero si DT es decir 1e7x100, entonces un j=sum(V1) agrupado debería ser mucho más rápido que un j=sum(get("V1")) agrupado por ese motivo. Al menos, eso es lo que se supone que debe suceder, y si no es así, puede ser un error. Si, por otro lado, muchas consultas se construyen dinámicamente y se repiten, puede que llegue el tiempo a paste0 y parse. Todo depende realmente. La configuración verbose=TRUE debe imprimir un mensaje sobre qué columnas se han detectado como utilizadas por j, de modo que se puedan verificar.

+0

Gracias, volviendo a la pregunta original, ¿cómo hago esto con su solución getResult <- function (dt, expr, gby) { print (dt [, eval (expr), por = eval (b)]) } v1 <- "Sepal.Length" v2 <- "Species" e <- parse (text = paste ("suma (", v1, ", na.rm = TRUE)")) b <- parse (text = v2) # rDT2 <- dt [, eval (e), por = eval (b)] dtR <- getResult (dt, e, b) – user1157129

+0

@ user1157129, Disculpe la omisión de la función como se solicita en tu pregunta. Por favor, mira la edición para una sugerencia. – BenBarnes

+0

Lo siento Ben, no está funcionando, ¿estoy haciendo algo? getResult <- function (dt, expr, gby) { return (dt [, eval (expr), por = eval (gby)]) } dt <- data.table (iris) v1 <- "Sepal.Length" v2 <- "Species" e <- parse (text = paste ("suma (", v1, ", na.rm = TRUE)")) b <- parse (text = v2) dtR <- getResult (dt = dt, expr = e, gby = b) – user1157129

Cuestiones relacionadas