install.packages("tidyverse")
install.packages("haven")
Clase 4 - Introducción al uso y aplicación de paquetes estadísticos para el tratamiento de fuentes de información en investigación social cuantitativa
1 Importación de datos
1.1 Librerías
Para esta clase, necesitaremos tener instaladas las siguientes librerías:
1.2 El formato .csv
Vamos a comenzar cargando los datos que utilizaremos a lo largo del seminario. La función que usemos para ello dependerá del formato en el que se encuentren los datos. En este caso, empezaremos cargando la base del CENSO 2010 que corresponde a la unidad de análisis hogar. Usando R base, podemos leer los datos a través de la función read.csv()
.
<- read.csv("bases/censo10_hogares.csv", sep = ";") censo_hogares
Otra forma de cargar los datos es a través del paquete readr
1. Este paquete es parte del tidyverse y es una alternativa más rápida y eficiente para leer datos. Para cargar los datos con readr
, primero llamamos a la librería tidyverse y luego usamos la función read_csv()
.
library(tidyverse)
<- read_csv2("bases/censo10_hogares.csv", progress = show_progress()) censo_hogares
Fijense que lo que le estamos indicando a R
es que abra el archivo que se encuentra en la dirección bases/censo10_hogares.csv
, que se encuentra en la carpeta del proyecto, y que lo guarde en un objeto llamado censo_hogares.
Para comprobar que la operación se realizó con éxito debemos revisar el ambiente de trabajo (environment). En dicha ventana, se nos indica la cantidad de observaciones (12197647 hogares) y variables (26) que tiene el objeto en cuestión. Si hacemos click en el mismo, accederemos a la base de datos completa.
1.3 El formato nativo: .rds
Otra forma de guardar y cargar datos es a través del formato nativo de R
: .rds. Para guardar un objeto en este formato, usamos la función saveRDS()
y para cargarlo, usamos readRDS()
.
Ahora probaremos abrir la base de personas del CENSO 2010, en el que cada caso representa a cada persona censada en el país en aquel año. Nuevamente, para abrir este archivo debemos asignarselo a un objeto, en este caso lo llamaremos censo_personas.
<- readRDS("bases/censo10_personas.rds") censo_personas
Si bien esto dependera de la memoria RAM de cada computadora, abrir un archivo en formato .rds suele ser considerablemente más rápido que abrir un archivo en formato .csv, sobre todo cuando tienen una gran cantidad de casos y de variables.
Como podemos observar desde el ambiente de trabajo, la base de datos de personas tiene 40117096 observaciones y 20 variables.
1.4 Abriendo otros formatos
Desde R
también podemos abrir otros formatos comunmente utilizados de forma sencilla. Por ejemplo, si queremos abrir un archivo en formato .xlsx o .xls podemos hacerlo a través del paquete readxl
. Por otro lado, si queremos traer datos específicos en formato .dta (Stata) o .sav (SPSS), podemos hacerlo a través de los paquetes haven
y foreign
, respectivamente, sin ningún inconveniente.
Por ejemplo, abramos un archivo en formato .sav con los que venimos trabajando en SPSS
. Vamos a probar con la base correspondiente a viviendas. La función que utilizaremos es read_spss()
del paquete haven
.
library(haven)
Warning: package 'haven' was built under R version 4.4.1
<- read_spss("bases/censo10_viviendas.sav") censo_viviendas
1.5 Trayendo datos desde la web
Otra de las potencialidades que ofrencen estas funciones es que permiten leer datos directamente desde alguna URL de la web. Por ejemplo, hagamos una prueba utilizando alguno de los datasets disponibles en el repositorio de datos abiertos de Argentina.
En este caso, seleccionaremos el registro de nacimientos en Argentina por departamento entre 2012 y 2022, elaborado por la Dirección Nacional de Población del RENAPER
<- read_csv("https://datosabiertos.renaper.gob.ar/nacimientos_por_departamento_y_anio_2012_2022.csv") nacimientos
1.6 Bonus track: paquetes de descarga de datos
Para algunas bases de datos, principalmente aquellas que se realizan con cierta frecuencia en el tiempo, existen paquetes específicos elaborados por usuarios o instituciones oficiales que permiten descargar los datos en forma, más o menos automática.
Algunos de estos paquetes solicitan acceso a una API (Application Programming Interface) para poder descargar los datos. Otros, simplemente, descargan los datos de la web. Si bien no es objeto de este seminario explorar estas alternativas, algunos ejemplos de paquetes de descarga de datos son:
ipumsr
: permite la manipulación y descarga de archivos del proyecto IPUMS, que contiene, entre otras fuentes, microdatos censales de distintos países.eph
: permite la descarga de datos de la Encuesta Permanente de Hogares (EPH) de Argentina. Al mismo tiempo facilita la construcción de paneles, pools de datos y estimaciones de pobreza.PNADcIBGE
: permite la descarga de datos de la Pesquisa Nacional por Amostra de Domicílios (PNAD) de Brasil.
2 Elementos de la base datos
2.1 Clases de objetos
Una vez abiertas las bases de datos, el siguiente paso que solemos dar es abrirla y observar como está dispuesta la matriz de datos. En el caso de RStudio
, a diferencia de SPSS, las bases de datos se mantienen ocultas en el ambiente de trabajo. Para visualizarlas, podemos hacer click en el objeto específico, o si queremos un resumen, podemos escribir el nombre del objeto en la consola o en el script.
censo_hogares
# A tibble: 12,197,647 × 26
redcode provincia departamento vivienda_ref_id hogar_ref_id nhog H05 H06
<chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 020010… CIUDAD A… 02001 1 1 1 1 4
2 020010… CIUDAD A… 02001 1 2 2 1 1
3 020010… CIUDAD A… 02001 1 3 4 1 3
4 020010… CIUDAD A… 02001 1 4 6 1 1
5 020010… CIUDAD A… 02001 2 5 1 1 1
6 020010… CIUDAD A… 02001 2 6 2 1 3
7 020010… CIUDAD A… 02001 2 7 3 1 2
8 020010… CIUDAD A… 02001 2 8 5 1 4
9 020010… CIUDAD A… 02001 2 9 7 1 1
10 020010… CIUDAD A… 02001 3 10 1 1 2
# ℹ 12,197,637 more rows
# ℹ 18 more variables: H07 <dbl>, H08 <dbl>, H09 <dbl>, H10 <dbl>, H11 <dbl>,
# H12 <dbl>, H13 <dbl>, H14 <dbl>, H15 <dbl>, H16 <dbl>, H19A <dbl>,
# H19B <dbl>, H19C <dbl>, H19D <dbl>, PROP <dbl>, INDHAC <dbl>,
# TOTPERS <dbl>, ALGUNBI <dbl>
Como bien hemos visto, en el objeto censo_hogares, se puede observar la estructura tripartita del dato. En las filas se disponen los hogares, en las columnas las variables y en las celdas los valores de las variables para cada hogar. Cada hogar cuenta con un identificador único, que en este caso es la variable hogar_ref_id
. Esto refleja que la información se encuentra ordenada, o como se suele decir, en un formato tidy. Como veremos a continuación, paquetes estrella como dplyr
, ggplot2
y el resto de los del tidyverse
están diseñados para trabajar con datos ordenados.
Otra cuestión relevante es que las variables pueden ser de distintos tipos. Por ejemplo, algunas variables son numéricas, otras son categóricas y otras son de texto. Para saber qué tipo de variable es cada una, podemos usar la función class()
. Por ejemplo, la variable TOTPERS
es numérica, y cuenta la cantidad de personas que hay en el hogar. Mientras que la variable provincia
es cadena, ya que almacena el nombre de las provincias en formato texto.
class(censo_hogares$TOTPERS)
[1] "numeric"
class(censo_hogares$provincia)
[1] "character"
En la línea de código escrita recién podemos ver que para señalar a una variable en una base de datos, utilizando R base
se utiliza el símbolo $. Esto indica que estamos apuntando a una columna determinada del objeto especificado. El autocompletado es una gran ventaja cuando necesitamos identificar alguna columna.
Al observar la clase del objeto censo_hogares
, podemos ver que es un data.frame, específicamente en formato tibble. Este es el tipo de objeto que se utiliza en R
para almacenar bases de datos de estructura tabular.
class(censo_hogares)
[1] "spec_tbl_df" "tbl_df" "tbl" "data.frame"
2.2 Los factores
Hemos señalado anteriormente que otro tipo de variables son aquellas que son categóricas. En R
, estas variables son conocidas como factores y tienen la particularidad que tienen un conjunto conocido de valores posibles y sobre los cuales puede establecerse un orden. Su diferenciación, respecto a otros tipos de objetos como los character o numeric, radica en que algunos análisis estadísticos más avanzados requieren que las variables categóricas sean tratadas como factores.
Por ejemplo, en la base de hogares contamos con la variable PROP
, que indica el régimen de tenencia de la vivienda y del terreno en el que vive el hogar. Si bien la variable fue cargada como numérica, sabemos que, en realidad, es una variable categórica. Para convertirla en factor, usamos la función factor()
, en donde, además, podemos declarar las distintas etiquetas (labels) que tienen las categorías. Para no sobreescribir la variable original, la guardamos en una nueva variable llamada prop_factor
.
$prop_factor <- factor(censo_hogares$PROP,
censo_hogareslabels = c("No aplica",
"Propietario de la vivienda y del terreno",
"Propietario sólo de la vivienda",
"Inquilino",
"Ocupante por préstamo",
"Ocupante por trabajo",
"Otra situación"))
Con la función levels()
podemos ver los niveles que tiene la variable prop_factor
, es decir, como están ordenadas las categorías.
levels(censo_hogares$prop_factor)
[1] "No aplica"
[2] "Propietario de la vivienda y del terreno"
[3] "Propietario sólo de la vivienda"
[4] "Inquilino"
[5] "Ocupante por préstamo"
[6] "Ocupante por trabajo"
[7] "Otra situación"
Las variables de tipo factor son una de las principales diferencias existentes entre R
y otros programas estadísticos como SPSS o Stata. En estos las variables categóricas suelen tener un valor numérico y una etiqueta asociada a cada valor, en forma de metadata. En R
debemos utilizar paquetes específicos como labelled
para poder trabajar de forma similar.
3 Organizando datos y variables: selecciones, filtros y orden
Luego de importar los datos con los que trabajaremos y de haberlos inspeccionado, lo siguiente consiste en organizarlos para posteriormente poder transformarlos, analizarlos e interpretarlos. En este apartado, veremos cómo seleccionar, filtrar y ordenar los datos, basandonos en el ecosistema de funciones que nos provee el paquete dplyr
2 de tidyverse
. Fundamentalmente, revisaremos las funciones select()
, filter()
y arrange()
.
3.1 Selección de variables
A menudo trabajamos con bases de datos provenientes de registros o encuestas que contienen una gran cantidad de variables. En estos casos, es común que no todas las variables sean de interés para el análisis que queremos realizar. Otras veces, como en nuestro caso, disponemos de bases de datos, como el censo, que cuenta con una gran cantidad de filas más que de columnas. Así mismo, seleccionar algunas de las variables con las que vamos a trabajar es una buena opción para reducir el tamaño de la base de datos y facilitar su manipulación y guardado.
Supongamos que quisieramos generar un nuevo objeto que contenga solo las variables redcode
, provincia
, hogar_ref_id
y la variable factor prop_factor
. Para ello, utilizamos la función select()
y le pasamos como argumento el objeto de la base de datos y las variables que queremos seleccionar, generando un nuevo objeto que se llame censo_hogares_seleccion.
<- select(censo_hogares, redcode, provincia, hogar_ref_id, prop_factor) censo_hogares_seleccion
Fijense en el ambiente de trabajo, que el nuevo objeto tiene las mismas observaciones que el objeto original, pero solo tiene las variables que seleccionamos. La función select()
acepta también incluir rangos de variables, mediante el operador :
. Por ejemplo, si quisiéramos seleccionar las variables redcode
a hogar_ref_id
, podríamos hacerlo de la siguiente manera. Sobreescribimos el objeto censo_hogares_seleccion para que contenga las variables seleccionadas.
<- select(censo_hogares, redcode:hogar_ref_id) censo_hogares_seleccion
Otra forma de seleccionar variables es a través del operador -
, que nos permite excluir variables. Por ejemplo, si quisiéramos seleccionar todas las variables excepto provincia
, podríamos hacerlo de la siguiente manera.
<- select(censo_hogares, -provincia) censo_hogares_seleccion
La función, como todas las del paquete dplyr
, es muy flexible y permite realizar selecciones de variables de forma muy sencilla. Recomendamos inspeccionar la misma mediante el comando ?select
.
3.2 Filtrado de casos
Si con select
seleccionamos variables, con filter
seleccionamos casos. Es decir, filtramos las observaciones que cumplen con ciertas condiciones. Para esto es necesario conocer los operadores lógicos y relacionales que vimos en la clase anterior.
Por ejemplo, si sobre el objeto censo_hogares
quisiéramos seleccionar solo los hogares de la provincia de Mendoza, podríamos hacerlo de la siguiente manera.
<- filter(censo_hogares, provincia == "MENDOZA") censo_hogares_seleccion
Vemos que en total, la provincia de Mendoza, cuenta con 496132 hogares.
Otro ejemplo que podemos aplicar sobre la base de hogares, es quedarnos con aquellos hogares que tienen más de un miembro, o, en otras palabras, que no son unipersonales. Para ello, utilizamos el operador !=
que significa distinto.
<- filter(censo_hogares, TOTPERS != 1) censo_hogares_seleccion
También podríamos combinar ambos filtros, seleccionando hogares de Mendoza que no sean unipersonales, usando el operador lógico &.
<- filter(censo_hogares, provincia == "MENDOZA" & TOTPERS != 1) censo_hogares_seleccion
Las posibilidades son infinitas y dependiendo del filtro que querramos aplicar las expresiones lógico-relacionales pueden ser más o menos complejas.
No confundir el operador lógico == con el operador de asignación =. El primero se utiliza para comparar valores, mientras que el segundo se utiliza para asignar valores a una variable. En SPSS
se utiliza el operador = para ambos casos.
3.3 Ordenando los datos
Por último, la función arrange()
nos permite ordenar los datos de acuerdo a una o más variables. Por ejemplo, si quisiéramos ordenar los hogares de la provincia de Mendoza de acuerdo a la cantidad de personas que viven en ellos, podríamos hacerlo de la siguiente manera. Por defecto, la función ordena de forma ascendente, pero podemos cambiarlo a descendente utilizando la función desc()
.
<- arrange(censo_hogares_seleccion, TOTPERS)
censo_hogares_seleccion
<- arrange(censo_hogares_seleccion, desc(TOTPERS)) censo_hogares_seleccion
3.4 Facilitando el trabajo: el operador pipe
Ahora bien, aprovechando que estamos aprendiendo las principales funciones de dplyr
, vamos a aprender un nuevo modo de trabajo que nos permite una dinámica más sencilla y eficiente. Para esto haremos uso del operador pipe (%>%
), del paquete magrittr
(tidyverse), que nos permite encadenar funciones de forma más legible y eficiente.
Por ejemplo, partiendo de la base de hogares original, vamos a seleccionar las variables redcode, provincia, vivienda_ref_id, hogar_ref_id y prop_factor y vamos a guardarlas en un nuevo objeto llamado censo_hogares_seleccion. Pero además vamos a filtrar solo los hogares inquilinos y lo vamos a ordenar de formas ascendente por la variable hogar_ref_id.
<- censo_hogares %>%
censo_hogares_seleccion select(redcode, provincia, vivienda_ref_id, hogar_ref_id, prop_factor) %>%
filter(prop_factor == "Inquilino") %>%
arrange(hogar_ref_id)
Fijense que el uso del operador pipe no solo nos permite trabajar de un modo más eficiente, sino que también nos simplifica el trabajo de no tener que estar llamando al objeto en cada función que aplicamos. La base de datos que estamos transformando, es indicada en la primera línea, y luego cada función se aplica automáticamente sobre la misma.
El operador %>%
es una de las herramientas más poderosas de R
e iremos incorporando su uso a lo largo del curso. Es fácil de entender su lógica de funcionamiento. Permite que vayamos encadenando funciones, una por una, que apuntan a un único objeto que queda declarado en la primera línea. El atajo de teclado para invocarlo es a través de Ctrl + Shift + M
en Windows y Cmd + Shift + M
en Mac.
4 Transformando los datos: creación y modificación variables
Teniendo ya la base en formato ordenado, habiendo seleccionado aquellas variables que vayamos a utilizar y filtrando los casos que nos interesan, el siguiente paso en el trabajo cuantitativo suele ser la creación de nuevas variables o la modificación de las existentes.
Esta fase en el trabajo investigativo puede implicar, entre otras opciones:
Generar nuevas variables a partir de las existentes. Por ejemplo, realizar una sumatoria o resta aritmética, a partir de los datos disponibles en dos o más variables.
Recodificar una variable existente. Por ejemplo, reduciendo el número de categorías de una variable categórica o numérica (grupos etarios, niveles de ingreso, etc.).
Generar una nueva variable a partir del cumplimiento de determinadas condiciones combinadas. Generalmente este trabajo se realiza para construir variables complejas. Por ejemplo, crear una variable que indique el tipo de hogar en cada caso.
4.1 Creación de variables mediante cálculos y expresiones condicionales
Para realizar estas operaciones utilizaremos siempre la función mutate()
del paquete dplyr
. Básicamente esta función nos creará una nueva columna en la matriz de datos, que contendrá los valores que le indiquemos. Por ejemplo, vamos a intentar calcular el nivel de hacinamiento de los hogares, a partir de la cantidad de personas que viven en ellos. El hacinamiento es una variable utilizada para el estudio de las condiciones de vida de los hogares y representa el cociente entre la cantidad total de personas del hogar y la cantidad total de habitaciones o piezas de que dispone el mismo (sin contar baño/s y cocina/s).
Se considera una situación de hacinamiento crítico cuando hay 3 o más personas por cuarto. Para construir dicha indicador, primero vamos a identificar aquellas variables que necesitamos, es decir, el total de personas por hogar TOTPERS
y la cantidad de habitaciones H16
. Entonces, en primer lugar, vamos a crear una nueva variable llamada personas_hab
que represente el cociente entre ambas variables.
<- censo_hogares %>%
censo_hogares mutate(personas_hab = TOTPERS / H16)
Ya contamos con la información necesaria para clasificar a los hogares según su situación de hacinamiento. Por último, en una nueva variable, llamada hacinamiento
, vamos a asignar un valor de 1 a aquellos hogares que tengan más de 3 personas por habitación y un valor de 0 a aquellos que no cumplan con esta condición. Para ello, introduciremos una nueva función que nos permite plantear condiciones: case_when()
. Esta función es muy similar al IF
en SPSS
o la función ifelse()
de R base. case_when()
se pasa dentro del mutate, y se le indica la condición que se quiere evaluar y el valor que se le asignará a la nueva variable en caso de que se cumpla dicha condición, separado por el símbolo ~
. Cada argemento se separa por una coma.
<- censo_hogares %>%
censo_hogares mutate(hacinamiento = case_when(personas_hab > 3 ~ 1,
<= 3 ~ 0)) personas_hab
El cálculo del hacinamiento podría simplificarse aun más, concatenando ambas operaciones dentro de la función mutate()
.
<- censo_hogares %>%
censo_hogares mutate(personas_hab = TOTPERS / H16,
hacinamiento = case_when(personas_hab > 3 ~ 1,
<= 3 ~ 0)) personas_hab
Si queremos observar los resultados de la tarea realizada, podemos hacerlo a través de la función table()
.
table(censo_hogares$hacinamiento)
0 1
11719077 452598
4.2 Recodificación de variables
El combo mutate()
y case_when()
también nos permite recodificar variables, es decir, cambiar los valores de una variable por otros o reducir su número de categorías. Es una práctica frecuente en el análisis de datos, ya que permite simplificar, posteriormente, la interpretación de los resultados.
Por ejemplo, vayamos ahora a la base de personas. En ella, nos encontramos con la p03
que indica la edad de la persona. Vamos a recodificar esta variable en grupos etarios, de acuerdo a una clasificación clásica:
- 0 a 14 años
- 15 a 64 años
- 65 años y más
<- censo_personas %>%
censo_personas mutate(grupo_etario = case_when(p03 <= 14 ~ "0 a 14 años",
>= 15 & p03 <= 64 ~ "15 a 64 años",
p03 >= 65 ~ "65 años y más")) p03
Otra forma de indicar que queremos agrupar valores que se encuentran en un rango es través del operador de pertenencia %in%
que evalúa si los elementos de un vector están presentes en otro vector. Por ejemplo, podemos crear la misma variable de grupo_etario
del siguiente modo:
<- censo_personas %>%
censo_personas mutate(grupo_etario = case_when(p03 %in% 0:14 ~ "0 a 14 años",
%in% 15:64 ~ "15 a 64 años",
p03 >= 65 ~ "65 años y más")) p03
El operador %in%
también puede ser utilizado para identificar valores en un vector alfanumérico o de cadena. En ese caso debemos ingresar los valores a evaluar dentro de la función c(). Por ejemplo provincia %in% c("Buenos Aires", "Chaco", "Formosa")
.