Pregunta

Estoy atrapado con un pequeño problema con R data.table.Su ayuda es muy apreciada.Cómo hago esto:

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)

Recibo el siguiente error:

Error en suma(v1, na.rm = VERDADERO):'Tipo' (personaje) inválido de argumento

Ahora, ambos v1 y v2 pasar de otro programa como variable de carácter, así que no puedo hacer esto v1<- quote(Sepal.Length) lo que parece funcionar.

¿Fue útil?

Solución

Una alternativa a la respuesta de flodel 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

EDITAR:

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 cual el paste0 y eval \ quote Los métodos 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 inspecciona j para ver qué columnas utiliza, solo subconjuntos de las columnas utilizadas (Preguntas frecuentes 1.12 y 3.1).Usa base::all.vars(j) Para hacer eso.Cuando usas get() en j la columna que se utiliza está oculta de all.vars y data.table recurre a subconjuntos de todas las columnas en caso de que j la expresión los necesita (muy parecido a cuando el .SD símbolo se utiliza en j, para cual .SDcols se agregó para resolver).Si todas las columnas se utilizan de todos modos, entonces no hay diferencia, pero si DT es decir 1e7x100 entonces un agrupado j=sum(V1) debería ser mucho más rápido que un grupo j=sum(get("V1")) por esta razón.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, entonces el tiempo para paste0 y parse podría entrar en ello.Realmente todo depende.Configuración verbose=TRUE debería imprimir un mensaje sobre qué columnas se han detectado como utilizadas por j, para que se pueda comprobar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top