mutate_each / summarise_each en dplyr: ¿cómo selecciono ciertas columnas y doy nuevos nombres a las columnas mutadas?

Estoy un poco confundido sobre el verbo mutate_each.

Es bastante sencillo usar la mutate básica para transformar una columna de datos en, por ejemplo, puntajes z, y crear una nueva columna en su data.frame (aquí con el nombre z_score_data ):

 newDF % select(one_column) %>% mutate(z_score_data = one_column - (mean(one_column) / sd(one_column)) 

Sin embargo, dado que tengo muchas columnas de datos que me gustaría transformar, parece que probablemente debería usar el verbo mutate_each .

 newDF % mutate_each(funs(scale)) 

Hasta aquí todo bien. Pero hasta ahora no he podido averiguarlo:

  1. ¿Cómo puedo darles a estas nuevas columnas los nombres apropiados, como puedo en mutate ?
  2. ¿Cómo puedo seleccionar ciertas columnas que deseo mutar, como hice con select en el primer caso?

Gracias por tu ayuda.

Actualización para dplyr> = 0.4.3.9000

En la versión de desarrollo dplyr 0.4.3.9000 (al momento de escribir esto), nombrar dentro de mutate_each y summarise_each se ha simplificado como se indica en las Noticias :

El comportamiento de summarise_each() de summarise_each() y mutate_each() se ha modificado para que pueda forzar la inclusión de la función y el nombre de la variable: summarise_each(mtcars, funs(mean = mean), everything())

Esto es principalmente importante si desea aplicar solo 1 función dentro de mutate_each / summarise_each y desea dar a esa columna nuevos nombres.

Para mostrar la diferencia, aquí está la salida de dplyr 0.4.3.9000 usando la nueva funcionalidad de denominación, en contraste con la opción a.2 a continuación:

 library(dplyr) # >= 0.4.3.9000 iris %>% mutate_each(funs(mysum = sum(.)), -Species) %>% head() # Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_mysum Sepal.Width_mysum #1 5.1 3.5 1.4 0.2 setosa 876.5 458.6 #2 4.9 3.0 1.4 0.2 setosa 876.5 458.6 #3 4.7 3.2 1.3 0.2 setosa 876.5 458.6 #4 4.6 3.1 1.5 0.2 setosa 876.5 458.6 #5 5.0 3.6 1.4 0.2 setosa 876.5 458.6 #6 5.4 3.9 1.7 0.4 setosa 876.5 458.6 # Petal.Length_mysum Petal.Width_mysum #1 563.7 179.9 #2 563.7 179.9 #3 563.7 179.9 #4 563.7 179.9 #5 563.7 179.9 #6 563.7 179.9 

Si no proporciona nuevos nombres y solo proporciona 1 función, dplyr cambiará las columnas existentes (como lo hizo en versiones anteriores):

 iris %>% mutate_each(funs(sum), -Species) %>% head() # Sepal.Length Sepal.Width Petal.Length Petal.Width Species #1 876.5 458.6 563.7 179.9 setosa #2 876.5 458.6 563.7 179.9 setosa #3 876.5 458.6 563.7 179.9 setosa #4 876.5 458.6 563.7 179.9 setosa #5 876.5 458.6 563.7 179.9 setosa #6 876.5 458.6 563.7 179.9 setosa 

Supongo que esta nueva funcionalidad estará disponible a través de CRAN en la próxima versión de lanzamiento 0.4.4.


dplyr veriones <= 0.4.3:

¿Cómo puedo darles a estas nuevas columnas los nombres apropiados, como puedo en mutar?

a) 1 función aplicada en mutate_each / summarise_each

Si aplicas solo 1 función dentro de mutate_each o summarise_each , las columnas existentes se transformarán y los nombres se mantendrán como solían ser, a menos que proporciones un vector con nombre para mutate_each_ / summarise_each_ (ver opción a.4)

Aquí hay unos ejemplos:

a.1 solo 1 función -> mantendrá los nombres existentes

 iris %>% mutate_each(funs(sum), -Species) %>% head() # Sepal.Length Sepal.Width Petal.Length Petal.Width Species #1 876 459 564 180 setosa #2 876 459 564 180 setosa #3 876 459 564 180 setosa #4 876 459 564 180 setosa #5 876 459 564 180 setosa #6 876 459 564 180 setosa 

a.2 también si especifica una nueva extensión de nombre de columna:

 iris %>% mutate_each(funs(mysum = sum(.)), -Species) %>% head() # Sepal.Length Sepal.Width Petal.Length Petal.Width Species #1 876 459 564 180 setosa #2 876 459 564 180 setosa #3 876 459 564 180 setosa #4 876 459 564 180 setosa #5 876 459 564 180 setosa #6 876 459 564 180 setosa 

a.3 Especifique manualmente un nuevo nombre por columna (pero solo práctico para algunas columnas):

 iris %>% mutate_each(funs(sum), SLsum = Sepal.Length,SWsum = Sepal.Width, -Species) %>% head() # Sepal.Length Sepal.Width Petal.Length Petal.Width Species SLsum SWsum #1 5.1 3.5 1.4 0.2 setosa 876 459 #2 4.9 3.0 1.4 0.2 setosa 876 459 #3 4.7 3.2 1.3 0.2 setosa 876 459 #4 4.6 3.1 1.5 0.2 setosa 876 459 #5 5.0 3.6 1.4 0.2 setosa 876 459 #6 5.4 3.9 1.7 0.4 setosa 876 459 

a.4 Use un vector con nombre para crear columnas adicionales con nuevos nombres:

caso 1: mantener columnas originales

A diferencia de las opciones a.1, a.2 y a.3, dplyr mantendrá las columnas existentes sin cambios y creará nuevas columnas en este enfoque. Los nombres de las nuevas columnas son iguales a los nombres del vector nombrado que se crea de antemano ( vars en este caso).

 vars <- names(iris)[1:2] # choose which columns should be mutated vars <- setNames(vars, paste0(vars, "_sum")) # create new column names iris %>% mutate_each_(funs(sum), vars) %>% head # Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_sum Sepal.Width_sum #1 5.1 3.5 1.4 0.2 setosa 876.5 458.6 #2 4.9 3.0 1.4 0.2 setosa 876.5 458.6 #3 4.7 3.2 1.3 0.2 setosa 876.5 458.6 #4 4.6 3.1 1.5 0.2 setosa 876.5 458.6 #5 5.0 3.6 1.4 0.2 setosa 876.5 458.6 #6 5.4 3.9 1.7 0.4 setosa 876.5 458.6 

Caso 2: eliminar columnas originales

Como puede ver, este enfoque mantiene las columnas existentes sin cambios y agrega nuevas columnas con los nombres especificados. En caso de que no desee conservar las columnas originales, sino solo las columnas recién creadas (y las otras columnas), puede agregar una statement de select luego:

 iris %>% mutate_each_(funs(sum), vars) %>% select(-one_of(vars)) %>% head # Petal.Length Petal.Width Species Sepal.Length_sum Sepal.Width_sum #1 1.4 0.2 setosa 876.5 458.6 #2 1.4 0.2 setosa 876.5 458.6 #3 1.3 0.2 setosa 876.5 458.6 #4 1.5 0.2 setosa 876.5 458.6 #5 1.4 0.2 setosa 876.5 458.6 #6 1.7 0.4 setosa 876.5 458.6 

b) más de 1 función aplicada en mutate_each / summarise_each

b.1 Permita que dplyr descubra nuevos nombres

Si aplicó más de 1 función, puede dejar que dplyr descubra los nombres por sí mismo (y mantendrá las columnas existentes):

 iris %>% mutate_each(funs(sum, mean), -Species) %>% head() # Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_sum Sepal.Width_sum Petal.Length_sum #1 5.1 3.5 1.4 0.2 setosa 876 459 564 #2 4.9 3.0 1.4 0.2 setosa 876 459 564 #3 4.7 3.2 1.3 0.2 setosa 876 459 564 #4 4.6 3.1 1.5 0.2 setosa 876 459 564 #5 5.0 3.6 1.4 0.2 setosa 876 459 564 #6 5.4 3.9 1.7 0.4 setosa 876 459 564 # Petal.Width_sum Sepal.Length_mean Sepal.Width_mean Petal.Length_mean Petal.Width_mean #1 180 5.84 3.06 3.76 1.2 #2 180 5.84 3.06 3.76 1.2 #3 180 5.84 3.06 3.76 1.2 #4 180 5.84 3.06 3.76 1.2 #5 180 5.84 3.06 3.76 1.2 #6 180 5.84 3.06 3.76 1.2 

b.2 Especifique manualmente nuevos nombres de columna

Otra opción, al usar más de 1 función, es especificar la extensión del nombre de columna por su cuenta:

 iris %>% mutate_each(funs(MySum = sum(.), MyMean = mean(.)), -Species) %>% head() # Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_MySum Sepal.Width_MySum Petal.Length_MySum #1 5.1 3.5 1.4 0.2 setosa 876 459 564 #2 4.9 3.0 1.4 0.2 setosa 876 459 564 #3 4.7 3.2 1.3 0.2 setosa 876 459 564 #4 4.6 3.1 1.5 0.2 setosa 876 459 564 #5 5.0 3.6 1.4 0.2 setosa 876 459 564 #6 5.4 3.9 1.7 0.4 setosa 876 459 564 # Petal.Width_MySum Sepal.Length_MyMean Sepal.Width_MyMean Petal.Length_MyMean Petal.Width_MyMean #1 180 5.84 3.06 3.76 1.2 #2 180 5.84 3.06 3.76 1.2 #3 180 5.84 3.06 3.76 1.2 #4 180 5.84 3.06 3.76 1.2 #5 180 5.84 3.06 3.76 1.2 #6 180 5.84 3.06 3.76 1.2 

¿Cómo puedo seleccionar ciertas columnas que deseo mutar, como hice con select en el primer caso?

Puedes hacer eso al hacer referencia a las columnas que se mutarán (o dejar de lado) dando sus nombres como aquí (mutate Sepal.Length, pero no Species):

 iris %>% mutate_each(funs(sum), Sepal.Length, -Species) %>% head() 

Además, puede usar funciones especiales para seleccionar las columnas a mutar, todas las columnas que comienzan con o contienen una palabra determinada, etc. usando, por ejemplo:

 iris %>% mutate_each(funs(sum), contains("Sepal"), -Species) %>% head() 

Para obtener más información sobre esas funciones, consulte ?mutate_each y ?select ?mutate_each .

Edite 1 después del comentario:

Si desea utilizar la evaluación estándar, dplyr proporciona versiones SE de la mayoría de las funciones que terminan con un “_” adicional. Entonces en este caso usarías:

 x <- c("Sepal.Width", "Sepal.Length") # vector of column names iris %>% mutate_each_(funs(sum), x) %>% head() 

Observe el mutate_each_ que utilicé aquí.


Editar 2: actualizado con la opción a.4

mutate_each quedará obsoleto, considere usar mutate_at . De la documentación dplyr_0.5.0 :

En el futuro, mutate_each () y summarise_each () quedarán en desuso en favor de una familia de funciones más funcional: mutate_all (), mutate_at (), mutate_if (), summarise_all (), summarise_at () y summarise_if ().

Aplicar una función a todas las variables, excepto a las Species :

Advertencia: el parámetro ‘.cols’ está en desuso, ¡vea la nota en la parte inferior!

 iris %>% mutate_at(.cols=vars(-Species), .funs=funs(mysum = sum(.))) %>% head() Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_mysum Sepal.Width_mysum 1 5.1 3.5 1.4 0.2 setosa 876.5 458.6 2 4.9 3.0 1.4 0.2 setosa 876.5 458.6 3 4.7 3.2 1.3 0.2 setosa 876.5 458.6 4 4.6 3.1 1.5 0.2 setosa 876.5 458.6 5 5.0 3.6 1.4 0.2 setosa 876.5 458.6 6 5.4 3.9 1.7 0.4 setosa 876.5 458.6 Petal.Length_mysum Petal.Width_mysum 1 563.7 179.9 2 563.7 179.9 3 563.7 179.9 4 563.7 179.9 5 563.7 179.9 6 563.7 179.9 

Aplicar una función a un subconjunto de variables

 vars_to_process=c("Petal.Length","Petal.Width") iris %>% mutate_at(.cols=vars_to_process, .funs=funs(mysum = sum(.))) %>% head() Sepal.Length Sepal.Width Petal.Length Petal.Width Species Petal.Length_mysum Petal.Width_mysum 1 5.1 3.5 1.4 0.2 setosa 563.7 179.9 2 4.9 3.0 1.4 0.2 setosa 563.7 179.9 3 4.7 3.2 1.3 0.2 setosa 563.7 179.9 4 4.6 3.1 1.5 0.2 setosa 563.7 179.9 5 5.0 3.6 1.4 0.2 setosa 563.7 179.9 6 5.4 3.9 1.7 0.4 setosa 563.7 179.9 

¡Actualizar! para la versión dplyr 0.7.1 (2017-08-08)

Si ves el mensaje:

.cols ha cambiado de nombre y está en desuso, use .vars

luego cambie .cols por .vars .

 iris %>% mutate_at(.vars=vars(-Species), .funs=funs(mysum = sum(.))) %>% head() 

Otro ejemplo:

 iris %>% mutate_at(.vars=vars(Sepal.Width), .funs=funs(mysum = sum(.))) %>% head() 

Es equivalente a:

 iris %>% mutate_at(.vars=vars("Sepal.Width"), .funs=funs(mysum = sum(.))) %>% head() 

Además, en esta versión, mutate_each está en desuso:

mutate_each() está en desuso. Utilice mutate_all() , mutate_at() o mutate_if() lugar. Para asignar funs a una selección de variables, use mutate_at()