Introducción

Hasta este punto hemos visto como importar bases de datos y a partir de las funciones básicas realizamos una primera exploración a las bases. Además de la primera exploración, uno de los puntos importantes luego de importar dataframes, es la manipulación de los datos que contiene el dataframe con el que estamos trabajando. Es decir, verificar si los datos han sido cargados correctamente y decidir de qué manera adecuarlo a nuestros intereses de la investigación, así como también poder realizar resúmenes con estos datos. Existe un paquete llamado dplyr el cual es muy útil y fue diseñado para manipular dataframes. Este paquete contiene una serie de funciones que nos permiten manipular los datos para el análisis de los mismos. A continuación se presenta una tabla que resume las funciones más utilizadas de este paquete.

Tabla 5

Función Ejemplo de sintaxis
arrange() arrange(variable1, variable2)
left_join() dataframe1 %>% left_join(., dataframe2, by = “variable”)
filter() filter(condición lógica según valor de variable). Ejemplo, filter(variable == “valor”)
select() select(variable1, variable2)
mutate() mutate(variable_nueva = operación entre variables). Ejemplo: mutate(var_nueva = variable1/variable2)
case_when case_when(condicion1 ~ “Valor1”, condicion2 ~ “Valor2”, condicion3 ~ “Valor3”)
rename() rename(nombre_nuevo = nombre_viejo)
summarise() summarise(nombre_col = medida(variable)
group_by() group_by(variable1) %>% summarise(nombre_col = medida(variable)

Iremos viendo más adelante cada una de estas funciones.

Instalación

Podemos instalar el paquete Tidyverse que contiene al paquete dplyr entre otros paquetes útiles para el analisis de datos o directamente instalar dplyr individualmente.

# Instalar tidyverse
install.packages("tidyverse")

# O sino instalar solo dplyr
install.packages("dplyr")

Pipe

Este paquete está diseñado para que todas las funciones trabajen encadenadamente mediante la utilización del pipe (tubería), el cual se escribe con el caracter %>% (se realiza combinando las teclas Ctrl + Shift + M o Cmd + Shift + M en Mac). La acción que realiza el pipe es llamar a un objeto que se encuentra a la izquierda y transformarlo mediante la función que se le indique a la derecha. El objeto que se indique a la izquierda no se verá afectado por cambios, a menos que se lo índique. Iremos viendo con más detalle en los ejemplos. Ahora vamos a ver ejemplos para cada una de las funciones de este paquete trabajando con las bases que importamos anteriormente.

Ordenar

La función arrange permite ordenar la base de datos en base a algún valor de una o más variables. Mediante esta función vamos a ordenar las bases de los hogares y de las personas por las variables Número identificador de vivienda (nocues) y Número identificador de hogar (nhog).

# Abrimos la libreria
library(dplyr)
## Warning: package 'dplyr' was built under R version 3.5.3
# Ordenamos ambas bases con la funcion arrange 
hogares <- hogares %>% arrange(nocues, nhog)
personas <- personas %>% arrange(nocues, nhog)

Emparejar

Existen cuatro tipos de uniones para bases de datos en el paquete dplyr y puede encontrar más información al respecto de cada una de ellas aquí. De estas cuatro maneras de emparejar bases, solamente nos vamos a centrar en una, es decir, en la que se realiza mediante la función left_join. Siendo así, respetando la cantidad de casos y de variables que tiene la base de personas, vamos a agregar las variables de la base de hogares. Esto le haremos de la siguiente manera:

# Emparejar bases
pisac <- personas %>% left_join(., hogares, by = c("nocues", "nhog"))
# el . llama al objeto que está antes del pipe

Entonces, hemos emparejado ambas bases y además también guardamos este resultado en un nuevo dataframe que se llama pisac. De esta manera, en esta nueva base incorporamos a la base de las personas todas las variables de las base de los hogares respetando las variables que funcionan como “key” o “llave” (nocues y nhog).

Filtrar y seleccionar

Con la función filter es posible filtrar la base de datos acorde al cumplimiento de condiciones lógicas y la función select permite especificar la serie de columnas o variables que se desea conservar o descartar de un dataframe. A continuación se presenta una tabla que resume las distintas condiciones lógicas que podemos utilizar para filtrar casos con la funcion filter.

Tabla 6

Símbolo Significado Símbolo Significado
> Mayor que != Distinto a
< Menor que %in% Dentro del grupo
== Igual a is.na Es NA
>= Mayor o igual a !is.na No es NA
<= Menor o igual a &, | y, o

Fuente: https://derek-corcoran-barrios.github.io/Libro/_book/tidydata.html#filter

Entonces, a partir de esta nueva base pisac, que fue el resultado del emparejamiento de las bases personas y hogares, vamos a filtrar solamente los casos de la región del NEA y a su vez le pediremos que seleccione solamente algunas variables del total de variables que contiene el dataframe.

# Filtrar la base emparejada por la region NEA y seleccionar variables
NEA <- pisac %>% 
  filter(region.x == "NEA (Chaco, Corrientes, Formosa y Misiones)") %>% 
  select(v108, v109, v116, t_hogar, nivel_ed, v134a, 
estado, v179, nocues, nhog, f_calib3.x, region.x, aglo.x, v12, v14, v15, v16, v19, v235i, 
v237, v259a, v260a, v213bi)

De esta manera, tendríamos creado un nuevo dataframe que se llama NEA y que contiene únicamente los casos correspondientes a la región del NEA y 23 variables que fueron seleccionadas del dataframe llamado pisac.

Renombrar

Podemos cambiar los nombres a las variables con la función rename. A modo de ejemplo modifiquemos solo tres nombres de las variable v108 a Edad, v109 a Sexo y v116 a Est_civil.

# Renombrar variables
NEA <- NEA %>% rename(Edad = v108,
                      Sexo = v109,
                      Est_civil = v116)

Resumir

La función summarise nos permite realizar tablas de resúmenes numéricos con la información original de una variable. Vamos a crear a modo de ejemplo una tabla que contenga algunas medidas para la variable Ingreso total del hogar (v235i).

# Resumen 
Resumen_igreso <- NEA %>% summarise(Promedio_ing = mean(v235i),
                                    Mediana = median(v235i),
                                    Varianza = var(v235i),
                                    "Desvío estandar" = sd(v235i))

Resumen_igreso
##   Promedio_ing Mediana Varianza Desvío estandar
## 1     9925.995    7640 60203908        7759.118

Agrupar

La función group_by se complementa con la función summarise y permite generar resúmenes numéricos para cada valor categórico de una variable cualitativa. Por ejemplo, podemos generar la misma tabla de resumen anterior pero ahora agrupando las medidas para cada valor de la variable Nivel educativo (nivel_ed).

# Resumen por grupo
Ingreso_x_educ <- NEA %>% 
  group_by(nivel_ed) %>%  
  summarise(Promedio = mean(v235i),
            Mediana = median(v235i),
            Varianza = var(v235i),
            "Desvio estandar" = sd(v235i))

Ingreso_x_educ
## # A tibble: 11 x 5
##    nivel_ed                     Promedio Mediana  Varianza `Desvio estanda~
##    <fct>                           <dbl>   <dbl>     <dbl>            <dbl>
##  1 Menores de 5 años               9284.   6957     7.21e7            8492.
##  2 Sin instrucción (incluye nu~    6912.   5500     1.86e7            4310.
##  3 Primaria/EGB incompleto         8387.   6838     4.80e7            6932.
##  4 Primaria/EGB completo           7985.   6926.    2.69e7            5191.
##  5 Secundario/Polimodal incomp~    9215.   7000     4.18e7            6466.
##  6 Secundario/Polimodal comple~   11223.   9000     6.54e7            8090.
##  7 Terciario incompleto           10739.   9000     4.71e7            6866.
##  8 Terciario completo             13862.  11000     8.28e7            9098.
##  9 Universitario incompleto       13332.  11800     5.97e7            7729.
## 10 Universitario completo         20716.  18000     1.40e8           11827.
## 11 Educación especial              5249.   5700     6.38e6            2527.

Observe que en el caso del nombre de la columna Desvío estándar, el mismo está indicado entre comillas, esto permite crear nombres de columnas que estén separados con espacio.

Transformar

Utilizando la función mutate podemos agregar y crear nuevas variables a partir de operaciones con la misma o entre otras variables. Veamos cómo podemos recodificar una variable numérica realizando una operación matemática para crear y agregar al dataframe NEA la varibale Ingreso total del hogar per cápita (ITH_PC) que será resultado del cociente entre las variables Ingreso total del hogar imputado (v235i) y Tamaño del hogar (t_hogar).

# Recodificar variable
NEA <- NEA %>% mutate(ITH_PC = v235i/t_hogar)

# Observamos los cinco primeros valores 
head(NEA$ITH_PC, 5)
## [1] 1273.714 1273.714 1273.714 1273.714 1273.714

Caso cuando

La función case_when permite crear una nueva variable generando los valores de la misma a partir de condiciones específicas. En caso de que no se cumpla las condiciones indicadas la variable tomará valores NA (valor faltante o valor perdido). Esta función se complementa con la función mutate y es útil para recategorizar valores de una variable cualitativa. Continuemos recategorizando los valores de la variable Clase social de pertenencia (v260a), agrupando los valores en Clase baja, Clase obrera, Clase media y Clase alta.

# Primero observamos cuales son los valores de la variable
levels(NEA$v260a)
## [1] "Clase baja"       "Clase obrera"     "Clase media baja"
## [4] "Clase media"      "Clase media alta" "Clase alta"      
## [7] "NS/NR"
# Ahora recategorizamos los valores
NEA <- NEA %>% mutate(Clase_recod = 
               case_when(v260a == "Clase baja" ~ "Clase baja",
                         v260a == "Clase obrera" ~ "Clase obrera",
                         v260a %in% c("Clase media baja",
                                      "Clase media",
                                      "Clase media alta") ~ "Clase media",
                         v260a == "Clase alta" ~ "Clase alta",
                         v260a == "NS/NR" ~ "NS/NR")) %>% 
  mutate(Clase_recod = ordered(Clase_recod,               
                               levels = c("Clase baja",     # indicamos que se trata de 
                                          "Clase obrera",   # una variable ordinal
                                          "Clase media",    # y ordenamos los valores
                                          "Clase alta",
                                          "NS/NR")))
# Consultamos los valores
levels(NEA$Clase_recod)
## [1] "Clase baja"   "Clase obrera" "Clase media"  "Clase alta"  
## [5] "NS/NR"

Valores NA (missing values)

En R los valores faltantes o valores perdidos se los conocen como NA, es común que cuando trabajemos con bases de datos nos encontremos con estos valores. Para saber si una variable contiene valores NA se utiliza la función is.na la cual devuelve un resultado lógico, es decir, si el objeto contiene valores perdidos el resultado será TRUE, de lo contrario será FALSE. Veamos un ejemplo con la variable Condición de inactividad (v179).

# Observar valores NA para los primeros 5 casos
head(is.na(NEA$v179), 5)
## [1] FALSE  TRUE  TRUE  TRUE  TRUE

Observe que de los cinco primeros casos, cuatro son NA. Ahora bien, en este caso ¿realmente son valores perdidos? Se debe tener en cuenta que no siempre se trata de valores perdidos como tales, ya que si observamos el formulario de encuesta del PISAC podemos notar que esta variable Condición de inactividad surge de una sucesión de preguntas, es decir, la condición de inactividad de la persona va a ser únicamente en el caso de que la persona se declare inactiva en la pregunta anterior. Por lo tanto, en esta variable los valores NA en realidad son valores que no corresponden y no valores perdidos. Esta aclaración es importante y se debe tener en cuenta al momento que nos encontremos con valores NA. Por otra parte, un inconveniente frecuente que suele suceder con estos valores surge cuando queremos realizar alguna medida de resumen numérica, por ejemplo el promedio. Si la variable tiene valores NA lo más probable es que el resultado sea “NA” y para resolver esto se utiliza el argumento na.rm. Observemos un ejemplo con la variable Ingreso neto en ocupación principal (v213bi).

# Promedio de v213bi
mean(NEA$v213bi)
## [1] NA
# Omitir valores NA
mean(NEA$v213bi, na.rm = TRUE)
## [1] 1695.497

Observe que el promedio de los ingresos de la ocupacion principal de las personas es considerablemente bajo debido a que ésta variable presenta muchos casos con ingresos de 0 pesos. Por lo tanto, para corregir este problema tendremos que filtrar los datos con solo aquellos que presenten ingresos mayores a 0. Entonces, procedemos a hacerlo de la siguiente manera:

# Creamos la tabla filtrando
Ing_ocup_ppal <- pisac %>% 
  filter(v213bi > 0 &
           !is.na(v213bi)) %>%  # filtramos tambien por los casos que no son NA
  select(v213bi) # y seleccionamos solo esta variable 

# Calculamos ahora el promedio
mean(Ing_ocup_ppal$v213bi)
## [1] 6398.697

Otra caso particular con el que podemos encontrarnos al momento de manipular datos es la necesidad de convertir uno o más valores como NA. Por ejemplo, en nuestra base NEA la variable Edad se encuentra como tipo factor (categórica) y contiene dos valores “Menor de un año” y “99 años y más” que es necesario primero convertirlos en NA para poder hacer posteriormente el cambio de factor a numérica. Veamos el ejemplo:

# Convertimos los valores en NA
NEA$Edad[NEA$Edad == "Menor de un año" |
         NEA$Edad == "99 años y más"] <- NA 

# Pasamos primero de factor a character
NEA$Edad <- as.character(NEA$Edad)

# Por ultimo pasamos a numérica
NEA$Edad <- as.numeric(NEA$Edad)

Ahora, es posible recodificar la variable Edad como lo hicimos anteriormente con la funcion case_when, creando una nueva variable con categoría de edades.

# Primero observamos los valores para definir categorías
summary(NEA$Edad)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    1.00   14.00   26.00   31.43   47.00   97.00      34
# Establecemos las categorías
# Establecemos las categorías
NEA <- NEA %>% 
  mutate(Edad_recod = case_when(Edad %in% c(1:17)  ~ "Hasta 17", 
                                Edad %in% c(18:35) ~ "de 18 a 35",
                                Edad %in% c(36:97) ~ "36 y más")) %>% 
  mutate(Edad_recod = ordered(Edad_recod,
                              levels = c("Hasta 17", 
                                         "de 18 a 35",
                                         "36 y más")))
# Consultamos los valores
levels(NEA$Edad_recod)
## [1] "Hasta 17"   "de 18 a 35" "36 y más"

Referencias

Este post está basado en los siguientes materiales:

WICKHAM H., GROLEMUND G. “R for Data Science” (2017). Recuperado de: https://r4ds.had.co.nz/

MENDIZABAL S. “Taller de Introducción a R” (2017). Recuperado de: https://songeo.github.io/introduccion-r-bookdown/

WEKSLER G., KOZLOWSKI D., SHOKIDA N., “Curso de R para procesamiento de datos de la Encuesta Permanente de Hogares” (2018). Recuperado de: https://diegokoz.github.io/Curso_R_EPH_clases/