Aplicar diferentes funciones a columnas de un dataframe seleccionando las funciones por su nombre.
Digamos que tengo un dataframe con varias columnas, algunas de las cuales quiero transformar. Los nombres de las columnas definen qué transformación debe usarse.
library(tidyverse)
set.seed(42)
df <- data.frame(A = 1:100, B = runif(n = 100, 0, 1), log10 = runif(n = 100, 10, 100), log2 = runif(n = 100, 10, 100), log1p = runif(n = 100, 10, 100), sqrt = runif(n = 100, 10, 100))
trans <- list()
trans$log10 <- log10
trans$log2 <- log2
trans$log1p <- log1p
trans$sqrt <- sqrt
Idealmente, me gustaría usar una llamada across
donde los nombres de las columnas se emparejen con los nombres de las funciones trans y las transformaciones se realicen sobre la marcha.
La salida deseada es la siguiente:
df_trans <- df %>%
dplyr::mutate(log10 = trans$log10(log10),
log2 = trans$log2(log2),
log1p = trans$log1p(log1p),
sqrt = trans$sqrt(sqrt))
df_trans
Sin embargo, no quiero especificar manualmente cada transformación por separado. En el ejemplo representativo solo tengo 4, pero este número podría variar ser significativamente mayor, lo que haría que la especificación manual fuera engorrosa y propensa a errores.
He logrado emparejar los nombres de las columnas con las funciones convirtiendo la lista trans en un dataframe y realizando un left_join, pero luego no puedo llamar a la función en la columna trans_function.
trans_df <- enframe(trans, value = "trans_function")
df %>%
pivot_longer(cols = everything()) %>%
left_join(trans_df) %>%
dplyr::mutate(value = trans_function(value))
Error: Problema con la columna
mutate()
value
.
ivalue = trans_function(value)
.
x no se pudo encontrar la función "trans_function"
Creo que necesito encontrar una forma de llamar a las funciones de las columnas de la lista o encontrar otra forma de hacer coincidir los nombres de las funciones con los nombres de las columnas. Todas las ideas son bienvenidas.
davy.ai
Una solución es usar
purrr::imap()
para iterar sobre la listatrans
y aplicar la función de transformación adecuada a cada columna que coincida en el dataframe. Aquí tienes un ejemplo de código:El código primero crea nuevas columnas con los mismos nombres que aquellos en la lista
trans
, usandomutate(across())
. Luego, usaimap()
para iterar sobre la listatrans
y retornar valoresNA
para cualquier función de transformación que no coincida con un nombre de columna endf
. El resultado de esta operación es un dataframe con columnas que coinciden en nombres y valores para la función de transformación a aplicar.Finalmente,
mutate(across(where(is.list), ~ map2(.x, trans[[names(.)]], ~ .y(.x))))
aplica cada función de transformación a la respectiva columna en el dataframe. Elwhere(is.list)
filtra solo las columnas que son listas (es decir, las columnas con valores temporalesNA
).map2()
itera sobre los elementos coincidentes del dataframe y la listatrans
en paralelo, y aplica la función de transformación a cada elemento usando.y(.x)
.El dataframe resultante
df_trans
es el dataframe transformado con las columnas originales y nuevas. Las columnas temporales creadas por la operaciónmutate()
en la línea 2 pueden ser eliminadas usandoselect(-names(trans))
.¡Espero que esto te ayude!