Refiriéndose a columnas data.table por nombres guardados en variables

data.table es un fantástico paquete R y lo estoy usando en una biblioteca que estoy desarrollando. Hasta ahora todo va muy bien, excepto por una complicación. Parece ser mucho más difícil (en comparación con los marcos de datos convencionales) referirse a data.table columnas data.table utilizando nombres guardados en variables (como para marcos de datos sería, por ejemplo: colname="col"; df[df[,colname]<5,colname]=0 ).

Quizás lo que más complica las cosas es la aparente falta de consistencia de la syntax en esto en data.table . En algunos casos, eval(colname) y get(colname) , o incluso c(colname) parecen funcionar. En otros, DT[,colname, with=F] es la solución. Sin embargo, en otros, como, por ejemplo, las funciones set() y subset() , no he encontrado una solución en absoluto. Finalmente, un caso de uso extremo, aunque también bastante común, se discutió anteriormente ( pasando los nombres de las columnas a data.table mediante progtwigción ) y las soluciones propuestas, aunque aparentemente haciendo su trabajo, no parecían particularmente legibles …

Tal vez estoy complicando demasiado las cosas? Si alguien pudiera anotar una hoja de referencia rápida para referirse a los nombres de las columnas data.table usando variables para diferentes escenarios comunes, estaría muy agradecido.

ACTUALIZAR:

Algunos ejemplos específicos que funcionan siempre que pueda codificar nombres de columna:

 x.short = subset(x, abs(dist)<=100) set(x, which(x$val<10), "val", 0) 

Ahora suponga distcol="dist" , valcol="val" . ¿Cuál es la mejor manera de hacer lo anterior usando distcol y valcol , pero no dist y val ?

Si vas a realizar operaciones complicadas dentro de tus expresiones j , probablemente deberías usar eval y quote . Un problema con eso en la versión actual de data.table es que el entorno de eval no siempre se procesa correctamente: eval y quote en data.table (Nota: ha habido una actualización de esa respuesta basada en una actualización del paquete). – y la solución actual para eso es agregar .SD a eval . Por lo que puedo decir de algunas pruebas que he hecho esto, esto no afecta la velocidad (de la manera en que, por ejemplo, .SD[1] en j ).

Curiosamente, este problema solo afecta al j y estarás bien usando eval normalmente en i (donde .SD no está disponible de todos modos).

El otro problema es la asignación, y ahí tienes que tener cadenas. Conozco una forma de extraer el nombre de la cadena de una expresión citada: no es bonita, pero funciona. Aquí hay un ejemplo que combina todo junto:

 x = data.table(dist = c(1:10), val = c(1:10)) distcol = quote(dist) valcol = quote(val) x[eval(valcol) < 5, capture.output(str(distcol, give.head = F)) := eval(distcol)*sum(eval(distcol, .SD))] 

Observe que estaba bien, no añadiendo .SD en una eval(distcol) , pero no lo haré si lo saqué de la otra eval .

Otra opción es usar get :

 diststr = "dist" valstr = "val" x[get(valstr) < 5, c(diststr) := get(diststr)*sum(get(diststr))] 

¿Tal vez ya conoces esta solución?

 DT[[colname]] 

Esto está inspirado en la solución de @ eddi en los comentarios a continuación, utilizando el ejemplo de OP:

 set.seed(1) x = data.table(a = 1:10, b=rnorm(10)) colstr="b" col <- eval(parse(text=paste("quote(",colstr,")",sep=""))) x[eval(col)<0] x[eval(col)<0,c(colstr):=-100] 

Digamos que tiene el nombre de columna en la variable x , podría hacer

 colname = as.name(x) 

puede usar colname en la función de subset