Transformar variables
0. Objetivo de la práctica
El objetivo del práctico, es avanzar en el procesamiento de los datos a través de la transformación de las variables a utilizar. Para ello revisaremos procedimientos básicos para el manejo de datos con RStudio, profundizando específicamente en la función mutate
de dplyr
.
1. Recursos de la práctica
En este práctico utilizaremos la base de datos de la Encuesta de Caracterización Socioeconómica (CASEN), la cual fue procesada en el Práctico anterior.Recuerden siempre consultar el manual/libro de códigos antes de trabajar una base de datos.
2. Librerias a utilizar
En este práctico utilizaremos cuatro paquetes
-
pacman
: este facilita y agiliza la lectura de los paquetes a utilizar en R -
sjmisc
: explorar datos -
car()
: recodificar manteniendo las etiquetas -
tidyverse
: colección de paquetes, del cuál utilizaremosdplyr
yforcats
-
dplyr
: para manipular datos -
forcats
: para transformar variables en factores
Pasos del procesamiento
1. Cargar librerías
Primero instalamos pacman
por única vez
install.packages("pacman")
library (pacman)
Luego cargaremos así los paquetes. Les recordamos que cuando luego de un paquete ponemos ::
esto se refiere a que se “fuerza” que esa función provenga de ese paquete
pacman::p_load(tidyverse,
haven,
forcats,
car,
sjmisc)
2. Cargar base de datos
datos <- read_dta("input/data/datos_proc.rds")
En el panel Environment, visualizamos el nuevo objeto, que posee 76.935 observaciones (o filas), y 11 variables (columnas)
head(datos)
## # A tibble: 6 x 11
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <dbl+lbl> <dbl> <dbl> <dbl+> <dbl+> <dbl+> <dbl+>
## 1 110110010301 Hombre 20 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 2 [No]
## 2 110110010301 Mujer 56 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 1 [Sí]
## 3 110110010401 Hombre 77 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 4 110110010401 Mujer 60 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 5 110110020301 Hombre 18 2 [No] 1.32e6 4 1 [Sí] 2 [No] 2 [No] 2 [No]
## 6 110110030101 Hombre 82 2 [No] 1.11e6 4 2 [No] 2 [No] 2 [No] 1 [Sí]
## # ... with 1 more variable: o6 <dbl+lbl>
3. mutate()
para transformación de variables
La función de mutate()
permite hacer operaciones para crear nuevas variables o transformar las ya existentes.
mutate()
en base a cálculo
Calcularemos una nueva variable llamada nueva_variable
que proviene de la suma de 2+3. También una variable ingreso_percapita
que proviene de la división del ingreso total del hogar y el número de personas que residen en el hogar
mutate(datos, nueva_variable = 3+2)
## # A tibble: 76,935 x 12
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <dbl+lbl> <dbl> <dbl> <dbl+> <dbl+> <dbl+> <dbl+>
## 1 110110010301 Hombre 20 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 2 [No]
## 2 110110010301 Mujer 56 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 1 [Sí]
## 3 110110010401 Hombre 77 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 4 110110010401 Mujer 60 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 5 110110020301 Hombre 18 2 [No] 1.32e6 4 1 [Sí] 2 [No] 2 [No] 2 [No]
## 6 110110030101 Hombre 82 2 [No] 1.11e6 4 2 [No] 2 [No] 2 [No] 1 [Sí]
## 7 110110030201 Hombre 56 2 [No] 3.02e5 2 1 [Sí] 2 [No] 2 [No] 1 [Sí]
## 8 110110030301 Mujer 77 2 [No] 7.40e5 1 2 [No] 2 [No] 2 [No] 1 [Sí]
## 9 110110030901 Mujer 17 2 [No] 2.19e6 4 2 [No] 2 [No] 2 [No] 2 [No]
## 10 110110031401 Mujer 74 2 [No] 1.22e6 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 2 more variables: o6 <dbl+lbl>,
## # nueva_variable <dbl>
mutate(datos, nueva_variable = 3+2,
ingreso_percapita = ytoth/tot_per)
## # A tibble: 76,935 x 13
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <dbl+lbl> <dbl> <dbl> <dbl+> <dbl+> <dbl+> <dbl+>
## 1 110110010301 Hombre 20 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 2 [No]
## 2 110110010301 Mujer 56 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 1 [Sí]
## 3 110110010401 Hombre 77 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 4 110110010401 Mujer 60 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 5 110110020301 Hombre 18 2 [No] 1.32e6 4 1 [Sí] 2 [No] 2 [No] 2 [No]
## 6 110110030101 Hombre 82 2 [No] 1.11e6 4 2 [No] 2 [No] 2 [No] 1 [Sí]
## 7 110110030201 Hombre 56 2 [No] 3.02e5 2 1 [Sí] 2 [No] 2 [No] 1 [Sí]
## 8 110110030301 Mujer 77 2 [No] 7.40e5 1 2 [No] 2 [No] 2 [No] 1 [Sí]
## 9 110110030901 Mujer 17 2 [No] 2.19e6 4 2 [No] 2 [No] 2 [No] 2 [No]
## 10 110110031401 Mujer 74 2 [No] 1.22e6 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 3 more variables: o6 <dbl+lbl>,
## # nueva_variable <dbl>, ingreso_percapita <dbl>
recode()
y mutate()
Muchas veces, los valores originales no se ajustan a los análisis que queramos hacer, o a la forma en que deseamos presentar nuestros análisis. Por ello, en el código de procesamiento recodificaremos frecuentemente los valores que alcanzan nuestras variables, especialmente cuando trabajamos con variables categóricas.
En el siguiente ejemplo recodificamos las categorías de respuesta de Mujer a Femenino y de Hombre a Masculino
datos %>%
mutate(sexo = dplyr::recode(sexo, "Mujer" = "Femenino", "Hombre" = "Masculino"))
## # A tibble: 76,935 x 11
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <dbl+lbl> <dbl> <dbl> <dbl+l> <dbl+> <dbl+> <dbl+>
## 1 1.10e11 Mascu~ 20 2 [No] 3004167 3 2 [No] 2 [No] 2 [No] 2 [No]
## 2 1.10e11 Femen~ 56 2 [No] 3004167 3 2 [No] 2 [No] 2 [No] 1 [Sí]
## 3 1.10e11 Mascu~ 77 2 [No] 610250 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 4 1.10e11 Femen~ 60 2 [No] 610250 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 5 1.10e11 Mascu~ 18 2 [No] 1321481 4 1 [Sí] 2 [No] 2 [No] 2 [No]
## 6 1.10e11 Mascu~ 82 2 [No] 1110000 4 2 [No] 2 [No] 2 [No] 1 [Sí]
## 7 1.10e11 Mascu~ 56 2 [No] 302083 2 1 [Sí] 2 [No] 2 [No] 1 [Sí]
## 8 1.10e11 Femen~ 77 2 [No] 739833 1 2 [No] 2 [No] 2 [No] 1 [Sí]
## 9 1.10e11 Femen~ 17 2 [No] 2190000 4 2 [No] 2 [No] 2 [No] 2 [No]
## 10 1.10e11 Femen~ 74 2 [No] 1220000 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 1 more variable: o6 <dbl+lbl>
El problema de la función recode()
de dplyr
es que, si recodifico números etiquetados, se perderá la etiqueta, conservándose el nuevo valor. Esto es un problema recurrente si, por ejemplo, sólo deseo recodificar valores nulos (por ejemplo, transformar los valores 88
y 99
como NA
).
Frente a ello, con el tiempo nos hemos convencido de que la mejor solución hasta ahora es ocupar recode()
del paquete car
. Si recuerdan, dos funciones con el mismo nombre podrían producir conflictos y, por ello, especificaremos con car::recode()
que la función recode()
que ocupamos proviene del paquete car
datos %$% car::recode(.$variable, c(‘valor_orig1=nuevo_valor1;valor_org2=nuevo_valor2’))
Ojo: %$% es el primo hermano de %>% (básicamente funcionan igual, por lo que podemos emplear tranquilamente %>% si nos encontramos trabajando con mutate
)
¡Recodifiquemos caracteres! incluso: podemos transformar inmediatamente en factor
, y asignar un orden específico a los niveles que alcanza la variable. Incluyamos la recodificación en mutate()
datos %>%
mutate(sexo = car::recode(.$sexo, c('"Mujer"="Femenino";"Hombre"= "Masculino"'),
as.factor = T, # Transformar en factor
levels = c("Masculino", "Femenino"))) #Ordenamos los niveles del factor
## # A tibble: 76,935 x 11
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <dbl+lbl> <dbl> <dbl> <dbl+l> <dbl+> <dbl+> <dbl+>
## 1 1.10e11 Mascu~ 20 2 [No] 3004167 3 2 [No] 2 [No] 2 [No] 2 [No]
## 2 1.10e11 Femen~ 56 2 [No] 3004167 3 2 [No] 2 [No] 2 [No] 1 [Sí]
## 3 1.10e11 Mascu~ 77 2 [No] 610250 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 4 1.10e11 Femen~ 60 2 [No] 610250 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 5 1.10e11 Mascu~ 18 2 [No] 1321481 4 1 [Sí] 2 [No] 2 [No] 2 [No]
## 6 1.10e11 Mascu~ 82 2 [No] 1110000 4 2 [No] 2 [No] 2 [No] 1 [Sí]
## 7 1.10e11 Mascu~ 56 2 [No] 302083 2 1 [Sí] 2 [No] 2 [No] 1 [Sí]
## 8 1.10e11 Femen~ 77 2 [No] 739833 1 2 [No] 2 [No] 2 [No] 1 [Sí]
## 9 1.10e11 Femen~ 17 2 [No] 2190000 4 2 [No] 2 [No] 2 [No] 2 [No]
## 10 1.10e11 Femen~ 74 2 [No] 1220000 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 1 more variable: o6 <dbl+lbl>
Notemos que los character
siempre van entre comillas
ifelse()
para construir variables condicionales
La función ifelse()
permite construir variables en base a condiciones lógicas. Su estructura es la siguiente
TRUE
es el valor que se obtiene si la condición es verdadera, mientras que FALSE
es todo el resto de las opciones (o cuando es FALSA)
Crearemos una variable que dummy que indica si el informante accedió al Ingreso Familiar de Emergencia (IFE) o no
datos %>%
mutate(ife_d= ifelse(ife == 1, 1, 0))
## # A tibble: 76,935 x 12
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <dbl+lbl> <dbl> <dbl> <dbl+> <dbl+> <dbl+> <dbl+>
## 1 110110010301 Hombre 20 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 2 [No]
## 2 110110010301 Mujer 56 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 1 [Sí]
## 3 110110010401 Hombre 77 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 4 110110010401 Mujer 60 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 5 110110020301 Hombre 18 2 [No] 1.32e6 4 1 [Sí] 2 [No] 2 [No] 2 [No]
## 6 110110030101 Hombre 82 2 [No] 1.11e6 4 2 [No] 2 [No] 2 [No] 1 [Sí]
## 7 110110030201 Hombre 56 2 [No] 3.02e5 2 1 [Sí] 2 [No] 2 [No] 1 [Sí]
## 8 110110030301 Mujer 77 2 [No] 7.40e5 1 2 [No] 2 [No] 2 [No] 1 [Sí]
## 9 110110030901 Mujer 17 2 [No] 2.19e6 4 2 [No] 2 [No] 2 [No] 2 [No]
## 10 110110031401 Mujer 74 2 [No] 1.22e6 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 2 more variables: o6 <dbl+lbl>, ife_d <dbl>
Recordemos que usamos 1 porque ife
es una variable de tipo haven_labelled, por lo que es un número etiquetado. Ahora asignemos 1 a las mujeres que accedieron al IFE
datos %>%
mutate(ife_d= ifelse(ife == 1 & sexo == 'Mujer', 1, 0))
## # A tibble: 76,935 x 12
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <dbl+lbl> <dbl> <dbl> <dbl+> <dbl+> <dbl+> <dbl+>
## 1 110110010301 Hombre 20 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 2 [No]
## 2 110110010301 Mujer 56 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 1 [Sí]
## 3 110110010401 Hombre 77 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 4 110110010401 Mujer 60 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 5 110110020301 Hombre 18 2 [No] 1.32e6 4 1 [Sí] 2 [No] 2 [No] 2 [No]
## 6 110110030101 Hombre 82 2 [No] 1.11e6 4 2 [No] 2 [No] 2 [No] 1 [Sí]
## 7 110110030201 Hombre 56 2 [No] 3.02e5 2 1 [Sí] 2 [No] 2 [No] 1 [Sí]
## 8 110110030301 Mujer 77 2 [No] 7.40e5 1 2 [No] 2 [No] 2 [No] 1 [Sí]
## 9 110110030901 Mujer 17 2 [No] 2.19e6 4 2 [No] 2 [No] 2 [No] 2 [No]
## 10 110110031401 Mujer 74 2 [No] 1.22e6 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 2 more variables: o6 <dbl+lbl>, ife_d <dbl>
También podemos ocupar esta función como validador, por ejemplo, rellenando con valores lógicos como FALSE
cuando no hay información válida en ytoth
. Luego esos FALSE
podrían ser contados en otros procesos estadísticos
datos %>%
mutate(validador_ingreso = ifelse(is.na(ytoth), FALSE, TRUE))
## # A tibble: 76,935 x 12
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <dbl+lbl> <dbl> <dbl> <dbl+> <dbl+> <dbl+> <dbl+>
## 1 110110010301 Hombre 20 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 2 [No]
## 2 110110010301 Mujer 56 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 1 [Sí]
## 3 110110010401 Hombre 77 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 4 110110010401 Mujer 60 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 5 110110020301 Hombre 18 2 [No] 1.32e6 4 1 [Sí] 2 [No] 2 [No] 2 [No]
## 6 110110030101 Hombre 82 2 [No] 1.11e6 4 2 [No] 2 [No] 2 [No] 1 [Sí]
## 7 110110030201 Hombre 56 2 [No] 3.02e5 2 1 [Sí] 2 [No] 2 [No] 1 [Sí]
## 8 110110030301 Mujer 77 2 [No] 7.40e5 1 2 [No] 2 [No] 2 [No] 1 [Sí]
## 9 110110030901 Mujer 17 2 [No] 2.19e6 4 2 [No] 2 [No] 2 [No] 2 [No]
## 10 110110031401 Mujer 74 2 [No] 1.22e6 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 2 more variables: o6 <dbl+lbl>,
## # validador_ingreso <lgl>
case_when()
para construir variable en base a múltiples condiciones
Una función que se utiliza frecuentemente para colapsar categorías o construir categorías en base a varias condiciones es case_when()
por lo lógico y fácil que es de entender
case_when(variable == condicion ~ valor1, variable == condicion ~ valor2, TRUE ~ NA_real_)
- Donde, TRUE indica “todo el resto”, y el NA dependerá de la clase del valor de recodificación. En general, usaremos
NA_character_
para variables categóricas, yNA_real_
para variables numéricas.
Un ejemplo claro es cuando queremos construir categorías de edad
datos %>%
mutate(edad_tramo = case_when(edad <=39 ~ "Joven",
edad > 39 & edad <=59 ~ "Adulto",
edad > 59 ~ "Adulto mayor",
TRUE ~ NA_character_)) %>%
select(edad, edad_tramo)
## # A tibble: 76,935 x 2
## edad edad_tramo
## <dbl> <chr>
## 1 20 Joven
## 2 56 Adulto
## 3 77 Adulto mayor
## 4 60 Adulto mayor
## 5 18 Joven
## 6 82 Adulto mayor
## 7 56 Adulto
## 8 77 Adulto mayor
## 9 17 Joven
## 10 74 Adulto mayor
## # ... with 76,925 more rows
Como se puede ver, no solamente indicamos tramos de la variable edad, sino que utilizamos operadores lógicos (&
). Podríamos ocupar el que necesitemos, y sobre todo, también combinar variables (por ejemplo, crear una variable sexo-edad
)
datos %>%
mutate(sexo_edad_tramo = case_when(sexo == "Hombre" & edad <=39 ~ "Hombre joven",
sexo == "Mujer" & edad <=39 ~ "Mujer joven",
sexo == 'Hombre' & (edad > 39 & edad <=59) ~ "Hombre adulto",
sexo == 'Mujer' & (edad > 39 & edad <=59) ~ "Mujer adulta",
sexo == 'Hombre' & edad > 59 ~ "Adulto mayor",
sexo == 'Mujer' & edad > 59 ~ "Adulta mayor",
TRUE ~ NA_character_)) %>%
select(sexo, edad, sexo_edad_tramo)
## # A tibble: 76,935 x 3
## sexo edad sexo_edad_tramo
## <fct> <dbl> <chr>
## 1 Hombre 20 Hombre joven
## 2 Mujer 56 Mujer adulta
## 3 Hombre 77 Adulto mayor
## 4 Mujer 60 Adulta mayor
## 5 Hombre 18 Hombre joven
## 6 Hombre 82 Adulto mayor
## 7 Hombre 56 Hombre adulto
## 8 Mujer 77 Adulta mayor
## 9 Mujer 17 Mujer joven
## 10 Mujer 74 Adulta mayor
## # ... with 76,925 more rows
Calcular índices con rowwise()
Como sabemos, la librería dplyr
de tidyverse
provee diversas herramientas que nos permiten manipular los datos con los cuales nos encontramos trabajando. Una de ellas es su función rowwise()
, que posibilita agrupar los datos en razón de las filas. Esto es particularmente útil cuando, por ejemplo, queremos construir algún índice. En este caso, utilizaremos las variables ytoth y tot_per para determinar cuál es el ingreso per cápita de cada hogar
datos %>% #Especificamos que trabajaremos con el dataframe datos
rowwise() %>% #Especificamos que agruparemos por filas
mutate(ing_pc = ytoth/tot_per) %>% #Creamos una nueva variable llamada ing_tot, sumando los valores de ss_t, svar_t y reg_t para cada fila
ungroup() # Desagrupamos (dejamos de trabajar en razón de filas)
## # A tibble: 76,935 x 12
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <dbl+lbl> <dbl> <dbl> <dbl+> <dbl+> <dbl+> <dbl+>
## 1 110110010301 Hombre 20 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 2 [No]
## 2 110110010301 Mujer 56 2 [No] 3.00e6 3 2 [No] 2 [No] 2 [No] 1 [Sí]
## 3 110110010401 Hombre 77 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 4 110110010401 Mujer 60 2 [No] 6.10e5 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## 5 110110020301 Hombre 18 2 [No] 1.32e6 4 1 [Sí] 2 [No] 2 [No] 2 [No]
## 6 110110030101 Hombre 82 2 [No] 1.11e6 4 2 [No] 2 [No] 2 [No] 1 [Sí]
## 7 110110030201 Hombre 56 2 [No] 3.02e5 2 1 [Sí] 2 [No] 2 [No] 1 [Sí]
## 8 110110030301 Mujer 77 2 [No] 7.40e5 1 2 [No] 2 [No] 2 [No] 1 [Sí]
## 9 110110030901 Mujer 17 2 [No] 2.19e6 4 2 [No] 2 [No] 2 [No] 2 [No]
## 10 110110031401 Mujer 74 2 [No] 1.22e6 2 2 [No] 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 2 more variables: o6 <dbl+lbl>, ing_pc <dbl>
4. Las variantes de mutate()
Con lo que ya hemos revisado serán capaces de realizar un procesamiento completo y acabado de sus variables. Sin embargo, hay otras funciones hermanas de mutate() que les recomendamos en caso de querer agilizar procedimientos de procesamiento de datos.
a) mutate_at()
Imaginemos que deseamos trabajar al mismo tiempo con todas nuestras variables cuyos valores son 1 == Si y 2 == No. En el caso de las variables ocupacion
e ife
, que son números etiquetados, podemos desear realizar esa recodificación al mismo tiempo (recordemos que, para recodificar números etiquetados como factores, primero debemos transformar esas variables en numeric
). Empleando mutate()
, lo haríamos de la siguiente manera
datos %>%
mutate(ocupacion = as.numeric(.$ocupacion),
ife = as.numeric(.$ife)) %>%
mutate(ocupacion = car::recode(.$ocupacion, c("1 = 'Si'; 2 = 'No'"), as.factor = T),
ife = car::recode(.$ife, c("1 = 'Si'; 2 = 'No'"), as.factor = T))
## # A tibble: 76,935 x 11
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <fct> <dbl> <dbl> <fct> <dbl+> <dbl+> <dbl+>
## 1 110110010301 Hombre 20 No 3004167 3 No 2 [No] 2 [No] 2 [No]
## 2 110110010301 Mujer 56 No 3004167 3 No 2 [No] 2 [No] 1 [Sí]
## 3 110110010401 Hombre 77 No 610250 2 No 2 [No] 2 [No] 1 [Sí]
## 4 110110010401 Mujer 60 No 610250 2 No 2 [No] 2 [No] 1 [Sí]
## 5 110110020301 Hombre 18 No 1321481 4 Si 2 [No] 2 [No] 2 [No]
## 6 110110030101 Hombre 82 No 1110000 4 No 2 [No] 2 [No] 1 [Sí]
## 7 110110030201 Hombre 56 No 302083 2 Si 2 [No] 2 [No] 1 [Sí]
## 8 110110030301 Mujer 77 No 739833 1 No 2 [No] 2 [No] 1 [Sí]
## 9 110110030901 Mujer 17 No 2190000 4 No 2 [No] 2 [No] 2 [No]
## 10 110110031401 Mujer 74 No 1220000 2 No 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 1 more variable: o6 <dbl+lbl>
¿Un poco largo, no? mutate_at()
nos permite realizar el mismo procedimiento de recodificación a ambas variables, lo cual hace posible un código más eficiente. Tenemos que incorporar dos argumentos:
vars =
: indica qué variables vamos a trabajar.~()
: indica la función que aplicaremos a las variables especificadas en vars
datos %>%
mutate_at(vars(ocupacion, ife), ~(as.numeric(.))) %>%
mutate_at(vars(ocupacion, ife), ~(car::recode(., c("1 = 'Si'; 2 = 'No'"), as.factor = T)))
## # A tibble: 76,935 x 11
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4
## <dbl> <fct> <dbl> <fct> <dbl> <dbl> <fct> <dbl+> <dbl+> <dbl+>
## 1 110110010301 Hombre 20 No 3004167 3 No 2 [No] 2 [No] 2 [No]
## 2 110110010301 Mujer 56 No 3004167 3 No 2 [No] 2 [No] 1 [Sí]
## 3 110110010401 Hombre 77 No 610250 2 No 2 [No] 2 [No] 1 [Sí]
## 4 110110010401 Mujer 60 No 610250 2 No 2 [No] 2 [No] 1 [Sí]
## 5 110110020301 Hombre 18 No 1321481 4 Si 2 [No] 2 [No] 2 [No]
## 6 110110030101 Hombre 82 No 1110000 4 No 2 [No] 2 [No] 1 [Sí]
## 7 110110030201 Hombre 56 No 302083 2 Si 2 [No] 2 [No] 1 [Sí]
## 8 110110030301 Mujer 77 No 739833 1 No 2 [No] 2 [No] 1 [Sí]
## 9 110110030901 Mujer 17 No 2190000 4 No 2 [No] 2 [No] 2 [No]
## 10 110110031401 Mujer 74 No 1220000 2 No 2 [No] 2 [No] 1 [Sí]
## # ... with 76,925 more rows, and 1 more variable: o6 <dbl+lbl>
¡Podemos intearctuar también con otras funciones que ya hemos utilizado, como starts_with()
!
Atención: como pueden fijarse, utilizamos un punto (.) en el argumento donde usualmente iría esepcificada la variable que estamos trabajando. Tal punto indica recursividad, es decir, que la operación especificada en ~()
será ejecutada (en orden) a cada una de las variables que especificamos en vars =
.
b) mutate_if()
También podemos utilizar mutate()
a un conjunto de variables seleccionadas a partir de una condición. Por ejemplo, transformemos en factor
con forcats::as_factor()
a todas las variables que sean números etiquetados
datos %>%
mutate_if(is.labelled, ~(forcats::as_factor(.)))
## # A tibble: 76,935 x 11
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4 o6
## <dbl> <fct> <dbl> <fct> <dbl> <dbl> <fct> <fct> <fct> <fct> <fct>
## 1 1.10e11 Homb~ 20 No 3.00e6 3 No No No No No
## 2 1.10e11 Mujer 56 No 3.00e6 3 No No No Sí No
## 3 1.10e11 Homb~ 77 No 6.10e5 2 No No No Sí No
## 4 1.10e11 Mujer 60 No 6.10e5 2 No No No Sí No
## 5 1.10e11 Homb~ 18 No 1.32e6 4 Sí No No No No
## 6 1.10e11 Homb~ 82 No 1.11e6 4 No No No Sí No
## 7 1.10e11 Homb~ 56 No 3.02e5 2 Sí No No Sí No
## 8 1.10e11 Mujer 77 No 7.40e5 1 No No No Sí No
## 9 1.10e11 Mujer 17 No 2.19e6 4 No No No No No
## 10 1.10e11 Mujer 74 No 1.22e6 2 No No No Sí No
## # ... with 76,925 more rows
c) mutate_all()
Por último, puede suceder que queramos emplear el mismo procedimiento a todas las variables incluidas en nuestros datos. Por ejemplo, supongamos que (por algún motivo) deseamos transformar todas las variables en character
datos %>%
mutate_all(~(as.character(.)))
## # A tibble: 76,935 x 11
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4 o6
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 110110010~ Homb~ 20 2 30041~ 3 2 2 2 2 2
## 2 110110010~ Mujer 56 2 30041~ 3 2 2 2 1 2
## 3 110110010~ Homb~ 77 2 610250 2 2 2 2 1 2
## 4 110110010~ Mujer 60 2 610250 2 2 2 2 1 2
## 5 110110020~ Homb~ 18 2 13214~ 4 1 2 2 2 2
## 6 110110030~ Homb~ 82 2 11100~ 4 2 2 2 1 2
## 7 110110030~ Homb~ 56 2 302083 2 1 2 2 1 2
## 8 110110030~ Mujer 77 2 739833 1 2 2 2 1 2
## 9 110110030~ Mujer 17 2 21900~ 4 2 2 2 2 2
## 10 110110031~ Mujer 74 2 12200~ 2 2 2 2 1 2
## # ... with 76,925 more rows
Como podrán darse cuenta, en este caso no especificamos el argumento vars =
, pues con mutate_all()
estamos considerando a todas las variables.
5. Resumen con procesamiento de las variables
Hasta ahora, solo hemos creado una base de datos que selecciona variables. Ahora nos resta incorporar en un nuevo objeto los cambios que nos parezcan relevantes para la base de datos procesada que utilizaremos en nuestros análisis.
Como ya conocemos operadores que permiten concatenar procesos ( %>%
y %$%
) este procedimiento será mucho más fácil.
datos %>%
mutate(sexo = car::recode(.$sexo, c('"Mujer"="Femenino";"Hombre"= "Masculino"'),
as.factor = T, # Transformar en factor
levels = c("Masculino", "Femenino")),
ife_d= ifelse(ife == 1 & sexo == 'Mujer', 1, 0),
sexo_edad_tramo = case_when(sexo == "Masculino" & edad <=39 ~ "Hombre joven",
sexo == "Femenino" & edad <=39 ~ "Mujer joven",
sexo == 'Masculino' & (edad > 39 & edad <=59) ~ "Hombre adulto",
sexo == 'Femenino' & (edad > 39 & edad <=59) ~ "Mujer adulta",
sexo == 'Masculino' & edad > 59 ~ "Adulto mayor",
sexo == 'Femenino' & edad > 59 ~ "Adulta mayor",
TRUE ~ NA_character_)) %>%
mutate_if(is.labelled, ~(forcats::as_factor(.))) %>%
rowwise() %>%
mutate(ing_pc = ytoth/tot_per) %>%
ungroup()
## # A tibble: 76,935 x 14
## folio sexo edad ocupacion ytoth tot_per ife o2 o3 o4 o6
## <dbl> <fct> <dbl> <fct> <dbl> <dbl> <fct> <fct> <fct> <fct> <fct>
## 1 1.10e11 Mascu~ 20 No 3.00e6 3 No No No No No
## 2 1.10e11 Femen~ 56 No 3.00e6 3 No No No Sí No
## 3 1.10e11 Mascu~ 77 No 6.10e5 2 No No No Sí No
## 4 1.10e11 Femen~ 60 No 6.10e5 2 No No No Sí No
## 5 1.10e11 Mascu~ 18 No 1.32e6 4 Sí No No No No
## 6 1.10e11 Mascu~ 82 No 1.11e6 4 No No No Sí No
## 7 1.10e11 Mascu~ 56 No 3.02e5 2 Sí No No Sí No
## 8 1.10e11 Femen~ 77 No 7.40e5 1 No No No Sí No
## 9 1.10e11 Femen~ 17 No 2.19e6 4 No No No No No
## 10 1.10e11 Femen~ 74 No 1.22e6 2 No No No Sí No
## # ... with 76,925 more rows, and 3 more variables: ife_d <dbl>,
## # sexo_edad_tramo <chr>, ing_pc <dbl>
¡Ahora que estamos seguras/os sobre-escribimos la base!
datos_proc <- datos %>%
mutate(sexo = car::recode(.$sexo, c('"Mujer"="Femenino";"Hombre"= "Masculino"'),
as.factor = T, # Transformar en factor
levels = c("Masculino", "Femenino")),
ife_d= ifelse(ife == 1 & sexo == 'Mujer', 1, 0),
sexo_edad_tramo = case_when(sexo == "Masculino" & edad <=39 ~ "Hombre joven",
sexo == "Femenino" & edad <=39 ~ "Mujer joven",
sexo == 'Masculino' & (edad > 39 & edad <=59) ~ "Hombre adulto",
sexo == 'Femenino' & (edad > 39 & edad <=59) ~ "Mujer adulta",
sexo == 'Masculino' & edad > 59 ~ "Adulto mayor",
sexo == 'Femenino' & edad > 59 ~ "Adulta mayor",
TRUE ~ NA_character_)) %>%
mutate_if(is.labelled, ~(forcats::as_factor(.))) %>%
rowwise() %>%
mutate(ing_pc = ytoth/tot_per) %>%
ungroup()
Podemos visualizar la base resultante a partir de view_df()
de sjPlot
sjPlot::view_df(datos)
## Registered S3 methods overwritten by 'parameters':
## method from
## as.double.parameters_kurtosis datawizard
## as.double.parameters_skewness datawizard
## as.double.parameters_smoothness datawizard
## as.numeric.parameters_kurtosis datawizard
## as.numeric.parameters_skewness datawizard
## as.numeric.parameters_smoothness datawizard
## print.parameters_distribution datawizard
## print.parameters_kurtosis datawizard
## print.parameters_skewness datawizard
## summary.parameters_kurtosis datawizard
## summary.parameters_skewness datawizard
## Warning in sprintf("%i", as.integer(range(x[[index]], na.rm = T))): NAs
## introduced by coercion to integer range
ID | Name | Label | Values | Value Labels |
---|---|---|---|---|
1 | folio | Identificación hogar (comuna area seg viv hogar) | range: NA-NA | |
2 | sexo | Sexo | Hombre Mujer |
|
3 | edad | Edad | range: 15-110 | |
4 | ocupacion | o1. La semana pasada, ¿trabajó al menos una hora? | 1 2 |
SÃ No |
5 | ytoth | Ingreso total del hogar | range: 0-92666667 | |
6 | tot_per | Total de personas en el hogar | range: 1-6 | |
7 | ife | y26d_hog. Últimos 12 meses, ¿alguien recibió Ingreso Familiar de Emergencia? |
1 2 9 |
SÃ No No sabe |
8 | o2 | o2. Aunque no trabajó la semana pasada, ¿realizó alguna actividad? |
1 2 |
SÃ No |
9 | o3 | o3. Aunque no trabajó, ¿tenÃa algún empleo del cual estuvo ausente temporalmente |
1 2 |
SÃ No |
10 | o4 | o4. ¿Ha trabajado alguna vez? | 1 2 |
SÃ No |
11 | o6 | o6. ¿Buscó trabajo remunerado o cuenta propia en las últimas cuatro semanas? |
1 2 |
SÃ No |
6. Guardar base procesada
Para guardar la base de datos procesada, debes dirigir la ruta hacia tu Rproject
saveRDS(datos_proc, file = "output/datos_proc.rds")
Resumen
En este práctico aprendimos a
- Utilizar la función
mutate()
dedplyr
(¡y sus variantes!) - Construir variables condicionales con
ifelse()
ycase_when()
- Construir índices agrupando por filas con
rowwise()