usar - leer cadena de caracteres en c
Seleccionar/asignar a variables data.table qué nombres se almacenan en un vector de caracteres (3)
¿Cómo se refiere a las variables en una data.table
si los nombres de las variables se almacenan en un vector de caracteres? Por ejemplo, esto funciona para un data.frame
:
df <- data.frame(col1 = 1:3)
colname <- "col1"
df[colname] <- 4:6
df
# col1
# 1 4
# 2 5
# 3 6
¿Cómo puedo realizar esta misma operación para una tabla de datos, ya sea con o sin :=
notación? Lo obvio de dt[ , list(colname)]
no funciona (ni lo esperaba).
* Esta no es una respuesta realmente, 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 idea de su rendimiento. ¿Alguna sugerencia para mejorar? ¿Es seguro asumir que una nueva columna sin nombre siempre tendrá 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))
Tenga en cuenta que puedo hacer referencia muy bien en la suma () pero parece que no puedo asignarlo 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.
Tratar :
DT = data.table(col1 = 1:3)
colname = "col1"
DT[, colname, with = FALSE] # select
# col1
# 1: 1
# 2: 2
# 3: 3
DT[, (colname) := 4:6] # assign
# col1
# 1: 4
# 2: 5
# 3: 6
Esta última se conoce como columna plonk , porque reemplaza el vector completo de la columna por referencia. Si un subconjunto i
estaba presente, se subasignaría por referencia. Los parens alrededor (colname)
es una taquigrafía introducida en la versión v1.9.4 en CRAN Oct 2014. Aquí está la noticia:
Using `with = FALSE` with `:=` is now deprecated in all cases, given that wrapping
the LHS of `:=` with parentheses has been preferred for some time.
colVar = "col1"
DT[, colVar := 1, with = FALSE] # deprecated, still works silently
DT[, (colVar) := 1] # please change to this
DT[, c("col1", "col2") := 1] # no change
DT[, 2:4 := 1] # no change
DT[, c("col1","col2") := list(sum(a), mean(b)] # no change
DT[, `:=`(...), by = ...] # no change
Ver también la sección de Detalles en ?`:=`
:
DT[i, (colnamevector) := value]
# [...] The parens are enough to stop the LHS being a symbol
Y para responder más preguntas en comentarios, aquí hay una forma (como de costumbre, hay muchas maneras):
DT[, colname := cumsum(get(colname)), with = FALSE]
# col1
# 1: 4
# 2: 9
# 3: 15
o bien, es posible que le resulte más fácil leer, escribir y depurar solo para eval
y paste
, similar a la construcción de una declaración SQL dinámica para enviar a un servidor:
expr = paste0("DT[,",colname,":=cumsum(",colname,")]")
expr
# [1] "DT[,col1:=cumsum(col1)]"
eval(parse(text=expr))
# col1
# 1: 4
# 2: 13
# 3: 28
Si haces eso mucho, puedes definir una función auxiliar EVAL
:
EVAL = function(...)eval(parse(text=paste0(...)),envir=parent.frame(2))
EVAL("DT[,",colname,":=cumsum(",colname,")]")
# col1
# 1: 4
# 2: 17
# 3: 45
Ahora que data.table
1.8.2 optimiza automáticamente j
para la eficiencia, puede ser preferible usar el método eval
. El get()
en j
evita algunas optimizaciones, por ejemplo.
O bien, hay un set()
. Una forma baja, funcional y funcional de :=
, que estaría bien aquí. Ver ?set
.
set(DT, j = colname, value = cumsum(DT[[colname]]))
DT
# col1
# 1: 4
# 2: 21
# 3: 66
Para columnas múltiples y una función aplicada en 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
con lapply
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"