6.11 Creación y transformación de columnas

Las funciones de la familia mutate() simplifican enormemente el proceso de crear columnas en la base de datos. Algo muy interesante es que es posible aplicar una transformación a una columna que se está creando o modificando dentro de la misma función de mutate() y transmute() (revisa la COL_NUEVA4 en el siguiente código). La estructura base es:

# Usando mutate()
BASE_DE_DATOS %>% ... %>% 
  mutate(COL_NUEVA1 = FUNCION_DE_TRANSFORMACION(COL_ANTIGUA1),
         COL_NUEVA2 = FUNCION_DE_TRANSFORMACION(COL_ANTIGUA2),
         COL_NUEVA3 = FUNCION_DE_TRANSFORMACION(COL_ANTIGUA3),
         COL_NUEVA4 = FUNCION_DE_TRANSFORMACION(COL_NUEVA1))

# Usando transmute()
BASE_DE_DATOS %>% ... %>% 
  transmute(COL_NUEVA1 = FUNCION_DE_TRANSFORMACION(COL_ANTIGUA1),
         COL_NUEVA2 = FUNCION_DE_TRANSFORMACION(COL_ANTIGUA2),
         COL_NUEVA3 = FUNCION_DE_TRANSFORMACION(COL_ANTIGUA3),
         COL_NUEVA4 = FUNCION_DE_TRANSFORMACION(COL_NUEVA1))
El resultado de transformación con transmute() es el mismo, excepto que las nuevas columnas aparecerán solitarias en su propia tabla, separadas de la original. Con mutate(), las nuevas columnas aparecen adjuntas a la derecha de la última columna dentro de la tabla original.

Ejemplo 6.16 Se pretende ejemplificar un nuevo índice de la relación Poliomielitis - Sarampión utilizando la fórmula:

\[MP = 0.00001*\frac{\sqrt{\text{#Casos de Sarampión}}}{0.39*\text{#Casos de Polio}^2} \]

Crear la nueva columna MP operando las columnas Measles para Sarampión y Polio para Poliomielitis. Por motivos del ejemplo, seleccionar previamente únicamente las columnas de trabajo, junto con Country y Year para identificar en qué países y qué años se tuvo un mayor valor del índice. Reordenar la columna MP de modo descendente y mostrar las primeras 10 filas.

# con mutate()
WHO %>% 
  dplyr::select(Measles, Polio, Country, Year) %>% 
  mutate(MP = (0.00001*(sqrt(Measles) / 0.39 * Polio^2))) %>% 
  arrange(desc(MP)) %>% 
  head(10)
#    Measles Polio                          Country Year    MP
# 1   131441    99                            China 2008 91.11
# 2   109023    94                            China 2007 74.81
# 3    99602    94                            China 2006 71.50
# 4   124219    87                            China 2005 68.40
# 5   118712    86                           Malawi 2010 65.34
# 6    52628    99                            China 2014 57.65
# 7    52461    99                            China 2009 57.56
# 8    90387    86                            India 2015 57.01
# 9    88962    86                            China 2001 56.56
# 10  133802    77 Democratic Republic of the Congo 2011 55.61

# con transmute(), no es necesario seleccionar 
# debido a que solo se mostrará la columna creada
WHO %>% 
  transmute(MP = (0.00001*(sqrt(Measles) / 0.39 * Polio^2))) %>% 
  arrange(desc(MP)) %>% 
  head(10)
#       MP
# 1  91.11
# 2  74.81
# 3  71.50
# 4  68.40
# 5  65.34
# 6  57.65
# 7  57.56
# 8  57.01
# 9  56.56
# 10 55.61
Tabla 6.2: Funciones de la familia mutate() y transmute()
Función Descripción
mutate() Crea o modifica columnas especificadas una por una. El resultado muestra todas las columnas de la tabla original.
transmute() Crea o modifica columnas especificadas una por una. El resultado solo muestra las columnas creadas o modificadas.
mutate_all() Aplica una modificación a todas las columnas de una tabla.
mutate_at() Aplica la(s) modificación(es) solo a la(s) columna(s) especificada(s) en la tabla.
mutate_if() Aplica una modificación a todas las columnas que cumplan con una condición lógica.
mutate_each() Idéntica a mutate_all() es considerada obsoleta (deprecated). mutate_each_() también es obsoleta.
transmute_all() Aplica una modificación a todas las columnas de una tabla. Las exporta en una nueva tabla, no dentro de la original.
transmute_at() Aplica la(s) modificación(es) solo a la(s) columna(s) especificada(s) en la tabla. Las exporta en una nueva tabla, no dentro de la original.
transmute_if() Aplica una modificación a todas las columnas que cumplan con una condición lógica. Las exporta en una nueva tabla, no dentro de la original.
transmute_each() Idéntica a transmute_all() es considerada obsoleta (deprecated). transmute_each_() también es obsoleta.


6.11.0.1 mutate_all() y transmute_all()

Estas funciones aplicarán las funciones especificadas a todas las columnas de la tabla. Si alguna columna no cumple con lo necesario para se analizada, se genera error. Asegúrate de que la tabla por completo sea modificable con las funciones de transformación definidas. Como alternativa, se utiliza la función de dplyr select() para seleccionar las columnas de trabajo antes de aplicar mutate_all() o transmute_all(). La estructura básica es:

BASE_DE_DATOS %>% 
  mutate_all(.funs = lst(LISTA_DE_FUNCIONES))
Si la función a usar en el argumento .funs = require más de un argumento para funcionar, es mejor crear una función con todas los argumentos definidos tal y como se necesitan. Luego usa la función nueva dentro de alguna función de la familia mutate().

Ejemplo 6.20 Seleccionando las columnas Income, GDP y Life_exp, aplicar la función round() para redondear a un dígito los decimales de estas columnas. Crea previamente la función rr() para redondear a dos decimales un valor dado.

# Crear una función de rendondeo a dos decimales
rr <- function(x)round(x,2)

# Aplicar dentro de mutate_all
WHO %>% 
  dplyr::select(Income, GDP, Life_exp) %>% 
  mutate_all(.funs = lst(rr)) %>% 
  head(10)
#    Income    GDP Life_exp Income_rr GDP_rr Life_exp_rr
# 1   0.479 584.26     65.0      0.48 584.26        65.0
# 2   0.476 612.70     59.9      0.48 612.70        59.9
# 3   0.470 631.74     59.9      0.47 631.74        59.9
# 4   0.463 669.96     59.5      0.46 669.96        59.5
# 5   0.454  63.54     59.2      0.45  63.54        59.2
# 6   0.448 553.33     58.8      0.45 553.33        58.8
# 7   0.434 445.89     58.6      0.43 445.89        58.6
# 8   0.433 373.36     58.1      0.43 373.36        58.1
# 9   0.415 369.84     57.5      0.42 369.84        57.5
# 10  0.405 272.56     57.3      0.41 272.56        57.3

6.11.0.2 mutate_at() y transmute_at()

Estas funciones permite seleccionar las columnas de trabajo a las cuales se les aplicará algo. La estructura básica es:

BASE_DE_DATOS %>% 
  mutate_at(.vars = vars(COLUMNAS_DE_TRABAJO),
            .funs = lst(LISTA_DE_FUNCIONES))

BASE_DE_DATOS %>% 
  transmute_at(.vars = vars(COLUMNAS_DE_TRABAJO),
            .funs = lst(LISTA_DE_FUNCIONES))

Ejemplo 6.21 Siguiendo el ejemplo @ref:(exm:mutateall), recrear el resultado utilizando mutate_at(). Si se utiliza mutate_at() con toda la tabla, el resultado será la misma base de datos más las nuevas columnas transformadas. Para no imprimir tanta información, utiliza transmute_at()

# Crear una función de rendondeo a dos decimales
rr <- function(x)round(x,2)

# Aplicar dentro de mutate_all
WHO %>% 
  transmute_at(.vars = vars(Income, GDP, Life_exp),
            .funs = lst(rr)) %>% 
  head(10)
#    Income_rr GDP_rr Life_exp_rr
# 1       0.48 584.26        65.0
# 2       0.48 612.70        59.9
# 3       0.47 631.74        59.9
# 4       0.46 669.96        59.5
# 5       0.45  63.54        59.2
# 6       0.45 553.33        58.8
# 7       0.43 445.89        58.6
# 8       0.43 373.36        58.1
# 9       0.42 369.84        57.5
# 10      0.41 272.56        57.3

6.11.0.3 mutate_if() y transmute_if()

Como otras funciones nombradas como _if, estas permiten indicar una condición lógica para seleccionar solo las columnas que cumplan con dicha condición. Para establecer la condición se utiliza funciones de la familia is(), como is.numeric(). La estructura básica es:

BASE_DE_DATOS %>% 
  mutate_if(.predicate = FUNCIÓN_IS_SIN_PARÉNTESIS,
               .funs = lst(LISTA_DE_FUNCIONES))

BASE_DE_DATOS %>% 
  transmute_if(.predicate = FUNCIÓN_IS_SIN_PARÉNTESIS,
               .funs = lst(LISTA_DE_FUNCIONES))

Ejemplo 6.22 Aplicar la transformación a factor de las columnas del tipo carácter:

# Revisar la estructura de WHO
# Notar las columnas chr
str(WHO)

# Utilizar mutate_if()
WHO2 <- WHO %>% 
  mutate_if(is.character, as.factor)

# Revisar la estructura de WHO2
# Notar que las columnas chr cambiaron a Factor 
str(WHO2)