Dos formas de seleccionar variable (s) mediante programación:
with = FALSE
:
DT = data.table(col1 = 1:3)
colname = "col1"
DT[, colname, with = FALSE]
..
prefijo 'dot dot' ( ):
DT[, ..colname]
Para obtener una descripción más detallada de la ..
notación 'punto punto' ( ), consulte Nuevas funciones en 1.10.2 (actualmente no se describe en el texto de ayuda).
Para asignar a variable (s), coloque el LHS de :=
entre paréntesis:
DT[, (colname) := 4:6]
Este último se conoce como plonk de columna , porque reemplaza el vector de columna completo por referencia. Si i
hubiera un subconjunto , se subasignaría por referencia. El parens around (colname)
es una taquigrafía introducida en la versión v1.9.4 en CRAN de octubre de 2014. Aquí está la noticia :
El uso de with = FALSE
con :=
ahora está obsoleto en todos los casos, dado que :=
durante algún tiempo se ha preferido envolver el LHS de entre paréntesis.
colVar = "col1"
DT[, (colVar) := 1]
DT[, c("col1", "col2") := 1]
DT[, 2:4 := 1]
DT[, c("col1","col2") := list(sum(a), mean(b))]
DT[, `:=`(...), by = ...]
Consulte también la sección Detalles en ?`:=`
:
DT[i, (colnamevector) := value]
Y para responder más preguntas en el comentario, aquí hay una forma (como de costumbre, hay muchas formas):
DT[, colname := cumsum(get(colname)), with = FALSE]
o bien, puede que le resulte más fácil de leer, escribir y depurar sólo para eval
una paste
, similar a la construcción de una sentencia de SQL dinámico para enviar a un servidor:
expr = paste0("DT[,",colname,":=cumsum(",colname,")]")
expr
eval(parse(text=expr))
Si lo hace mucho, puede definir una función auxiliar EVAL
:
EVAL = function(...)eval(parse(text=paste0(...)),envir=parent.frame(2))
EVAL("DT[,",colname,":=cumsum(",colname,")]")
Ahora que data.table
1.8.2 optimiza automáticamente la j
eficiencia, puede ser preferible utilizar el eval
método. El get()
in j
evita algunas optimizaciones, por ejemplo.
O lo hay set()
. Una forma funcional de bajo costo, :=
que estaría bien aquí. Ver ?set
.
set(DT, j = colname, value = cumsum(DT[[colname]]))
DT
.
, o..
evitar cualquier posible enmascaramiento siDT
alguna vez contiene ese símbolo como nombre de columna en el futuro (y seguir la convención con la que los nombres de columna no comienzan.
). Hay algunas solicitudes de funciones para que sea más sólido para problemas de alcance como ese, como agregar.()
y..()
.fn$
del paquete gsubfn para mejorar la legibilidad de la solución de EVAL:library(gsubfn); fn$EVAL( "DT[,$colname:=cumsum($colname)]" )
.* Esta no es una respuesta en realidad, pero no tengo suficiente credibilidad en la calle para publicar comentarios: /
De todos modos, para cualquiera que esté buscando crear una nueva columna en una tabla de datos con un nombre almacenado en una variable, tengo lo siguiente para trabajar. No tengo ni idea de su rendimiento. ¿Alguna sugerencia de mejora? ¿Es seguro asumir que una nueva columna sin nombre siempre recibirá el nombre V1?
colname <- as.name("users") # Google Analytics query is run with chosen metric and resulting data is assigned to DT DT2 <- DT[, sum(eval(colname, .SD)), by = country] setnames(DT2, "V1", as.character(colname))
Observe que puedo hacer referencia a él bien en la suma () pero parece que no puedo hacer que se asigne en el mismo paso. Por cierto, la razón por la que necesito hacer esto es que colname se basará en la entrada del usuario en una aplicación Shiny.
fuente
V1
es el nuevo nombre. Por ejemplo, si lee csv confread
y hay una columna sin nombre, tendráV1
nombre (yread.csv
daráX
). Entonces es posible que su mesa ya tenga unV1
. Tal vez solo obtenga el nombre pornames(DT)[length(names(DT))]
Para múltiples columnas y una función aplicada a valores de columna.
Al actualizar los valores de una función, el RHS debe ser un objeto de lista, por lo que usar un bucle en
.SD
conlapply
hará el truco.El siguiente ejemplo convierte columnas enteras en columnas numéricas
a1 <- data.table(a=1:5, b=6:10, c1=letters[1:5]) sapply(a1, class) # show classes of columns # a b c1 # "integer" "integer" "character" # column name character vector nm <- c("a", "b") # Convert columns a and b to numeric type a1[, j = (nm) := lapply(.SD, as.numeric ), .SDcols = nm ] sapply(a1, class) # a b c1 # "numeric" "numeric" "character"
fuente
Recupere múltiples columnas de data.table a través de variable o función:
library(data.table) x <- data.table(this=1:2,that=1:2,whatever=1:2) # === explicit call x[, .(that, whatever)] x[, c('that', 'whatever')] # === indirect via variable # ... direct assignment mycols <- c('that','whatever') # ... same as result of a function call mycols <- grep('a', colnames(x), value=TRUE) x[, ..mycols] x[, .SD, .SDcols=mycols] # === direct 1-liner usage x[, .SD, .SDcols=c('that','whatever')] x[, .SD, .SDcols=grep('a', colnames(x), value=TRUE)]
que todos ceden
that whatever 1: 1 1 2: 2 2
Encuentro el
.SDcols
camino más elegante.fuente
Podrías intentar esto
colname <- as.name ("COL_NAME")
DT2 <- DT [, lista (COL_SUM = sum (eval (colname, .SD))), por = c (grupo)]
fuente