Aplicar una función a cada columna especificada en una tabla de datos y actualizarla por referencia

Resuelto Dean MacGregor asked hace 54 años • 7 respuestas

Tengo una tabla de datos con la que me gustaría realizar la misma operación en determinadas columnas. Los nombres de estas columnas se dan en un vector de caracteres. En este ejemplo particular, me gustaría multiplicar todas estas columnas por -1.

Algunos datos de juguetes y un vector que especifica columnas relevantes:

library(data.table)
dt <- data.table(a = 1:3, b = 1:3, d = 1:3)
cols <- c("a", "b")

Ahora mismo lo estoy haciendo de esta manera, recorriendo el vector de caracteres:

for (col in 1:length(cols)) {
   dt[ , eval(parse(text = paste0(cols[col], ":=-1*", cols[col])))]
}

¿Hay alguna manera de hacer esto directamente sin el bucle for?

Dean MacGregor avatar Jan 01 '70 08:01 Dean MacGregor
Aceptado

Esto parece funcionar:

dt[ , (cols) := lapply(.SD, "*", -1), .SDcols = cols]

El resultado es

    a  b d
1: -1 -1 1
2: -2 -2 2
3: -3 -3 3

Aquí hay algunos trucos:

  • Debido a que hay paréntesis en (cols) :=, el resultado se asigna a las columnas especificadas en cols, en lugar de a alguna nueva variable denominada "cols".
  • .SDcolsle dice a la llamada que solo estamos viendo esas columnas y nos permite usar .SD, el Subset de los Ddatos asociados con esas columnas.
  • lapply(.SD, ...)opera en .SD, que es una lista de columnas (como todos los marcos de datos y tablas de datos). lapplydevuelve una lista, por lo que al final jparece cols := list(...).

EDITAR : Aquí hay otra forma que probablemente sea más rápida, como mencionó @Arun:

for (j in cols) set(dt, j = j, value = -dt[[j]])
Frank avatar May 30 '2013 21:05 Frank

Me gustaría agregar una respuesta cuando desee cambiar también el nombre de las columnas. Esto resulta bastante útil si desea calcular el logaritmo de varias columnas, lo que suele ser el caso en el trabajo empírico.

cols <- c("a", "b")
out_cols = paste("log", cols, sep = ".")
dt[, c(out_cols) := lapply(.SD, function(x){log(x = x, base = exp(1))}), .SDcols = cols]
hannes101 avatar Mar 30 '2017 08:03 hannes101