# Numéricos
1
2
3.1
# Caracter o texto
"hola"
# Lógicos
TRUE
FALSE
Introducción a R
Documento de trabajo
1 Introducción
El presente código práctico aplicará las funciones fundamentales de Tidyverse a la Encuesta de Caracterización Socioeconómica Nacional (CASEN) de la edición 2022 reducida en su N. En función de los objetivos del curso, una variable fundamental será la pertencia a Pueblos Originarios. En particular, interesa describir las estadísticas a nivel educativo, ingreso autónomo, pobreza, entre otras.
La base oficial se puede encontrar En la página del Observatorio del Ministerio de Desarrollo Social.
2 Nociones previas: R Base
Estos son los tres tipos de datos más básicos en R: numéricos, texto (caracter) y lógicos. Todo lo que trabajemos en R parte desde estas formas elementales.
R funciona como una calculadora: puedes hacer operaciones directamente.
2 + 2 # suma
50 * 100 # multiplicación
4556 - 1000 # resta
6565 / 89 # división
Los operadores lógicos nos permiten hacer comparaciones entre valores. El resultado siempre será un valor lógico: TRUE o FALSE. Esto es fundamental para filtros y condicionales en análisis de datos.
1 == 1 # igualdad
1 == 2
40 != 30 # desigualdad
40 != 40
31 > 18 # mayor que
40 < 80 # menor que
40 >= 40 # mayor o igual
50 >= 40
4 <= 5 # menor o igual
R es un lenguaje basado en objetos. Podemos crear objetos (variables) con <- y luego reutilizarlos en operaciones. Esto es clave para construir flujos de trabajo limpios y organizados.
# Crear objeto
<- 1993
año
año
# Operaciones con objetos
+ 10
año 2024 - año
# Crear nuevo objeto a partir de un cálculo
<- 2024 - año
edad edad
3 Vamos a la CASEN desde Tidyverse
3.1 Cargar base de datos
Cargamos la base de datos directamente desde GitHub. Para hacerlo, solo hay que correr el código con Control/Command
+ Enter.
<- "https://raw.githubusercontent.com/centrociir/interculturales/refs/heads/main/clases/clase1/bbdd/casen2022_sample.csv"
url <- "casen2022_sample.csv"
destfile
# Leerla directamente en R
<- read.csv(destfile, encoding = "UTF-8")
casen head(casen)
region nse sexo ecivil educ pueblos_indigenas pobreza yautcor
1 4 7 2 8 6 0 3 660000
2 5 1 2 5 1 0 3 NA
3 16 2 2 8 2 0 3 NA
4 16 6 1 1 2 0 3 416667
5 5 6 2 8 0 0 3 NA
6 13 3 1 NA 1 0 3 NA
3.2 Cargar librería necesaria
#install.packages(tidyverse) En caso de no estar instalado
library(tidyverse)
library(dplyr)
3.3 Examinamos base de datos
¿Qué se hace acá? Se explora la estructura y el resumen estadístico de las variables de la base casen. Se identifican tipos de variables y rangos de valores.
|> glimpse() casen
Rows: 2,000
Columns: 8
$ region <int> 4, 5, 16, 16, 5, 13, 8, 1, 6, 13, 7, 8, 3, 2, 8, 14,…
$ nse <int> 7, 1, 2, 6, 6, 3, 4, 2, 6, 6, 7, 4, 1, 2, 4, 2, 1, 3…
$ sexo <int> 2, 2, 2, 1, 2, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2…
$ ecivil <int> 8, 5, 8, 1, 8, NA, 1, 8, 1, 2, 6, 1, 1, 1, 8, 5, NA,…
$ educ <int> 6, 1, 2, 2, 0, 1, 1, 3, 4, 11, 11, 3, 5, 1, 8, 6, 1,…
$ pueblos_indigenas <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0…
$ pobreza <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3…
$ yautcor <int> 660000, NA, NA, 416667, NA, NA, NA, NA, 1205833, NA,…
summary(casen) #Función de R base
region nse sexo ecivil
Min. : 1.00 Min. :1.000 Min. :1.00 Min. :1.000
1st Qu.: 5.00 1st Qu.:2.000 1st Qu.:1.00 1st Qu.:1.000
Median : 8.00 Median :3.000 Median :2.00 Median :2.000
Mean : 8.72 Mean :3.245 Mean :1.54 Mean :4.414
3rd Qu.:13.00 3rd Qu.:4.000 3rd Qu.:2.00 3rd Qu.:8.000
Max. :16.00 Max. :7.000 Max. :2.00 Max. :8.000
NA's :344
educ pueblos_indigenas pobreza yautcor
Min. :-88.000 Min. :0.000 Min. :1.000 Min. : 2083
1st Qu.: 1.000 1st Qu.:0.000 1st Qu.:3.000 1st Qu.: 250000
Median : 4.000 Median :0.000 Median :3.000 Median : 439167
Mean : 4.058 Mean :0.139 Mean :2.896 Mean : 600425
3rd Qu.: 6.000 3rd Qu.:0.000 3rd Qu.:3.000 3rd Qu.: 700000
Max. : 12.000 Max. :1.000 Max. :3.000 Max. :11518333
NA's :1 NA's :875
4 Empecemos a procesar!
4.1 Mutate y select: Crear, recodificar y seleccionar.
mutate()
sirve para crear nuevas variables o transformar variables existentes.
select()
permite elegir columnas específicas para inspeccionarlas o trabajar solo con ellas.
Ambas funciones son parte del flujo de trabajo de dplyr (Tidyverse), y se usan en cadena con el operador |> (pipe) para aplicar transformaciones claras y ordenadas.
Para saber la etiqueta correspondiente de las variables debemos acudir al libro de códigos de la Encuesta Casen que se encuentra aquí bajo el nombre “Libro de códigos Base de datos Casen 2022 (versión 18 marzo 2024)”.
La variable educación posee las siguientes etiquetas.
- Sin Educación Formal
- Básica incompleta
- Básica completa
- Media humanista incompleta
- Media técnica profesional incompleta
- Media humanista completa
- Media técnica profesional completa
- Técnico nivel superior incompleta
- Técnica nivel superior completo
- Profesional incompleto
- Postgrado incompleto
- Profesional completo
- Postgrado completo
En base a lo que aprendimos con la función mutate
podemos realizar la siguiente recodificación:
<- casen |> #Renombramos el objeto
casen ::mutate(
dplyreduc_nivel = dplyr::case_when(
%in% 0:1 ~ "Sin educación",
educ %in% 2:4 ~ "Básica",
educ %in% 5:6 ~ "Media",
educ %in% 7:8 ~ "Técnico nivel superior",
educ %in% 9:11 ~ "Profesional",
educ == 12 ~ "Postgrado",
educ TRUE ~ NA_character_
),educ_nivel = factor(educ_nivel, levels = c(
"Sin educación", "Básica", "Media",
"Técnico nivel superior", "Profesional", "Postgrado"
ordered = TRUE)
), )
Se usa mutate()
junto con case_when()
para crear una nueva variable categórica llamada educ_nivel
a partir de educ
, agrupando los valores numéricos en tramos más comprensibles.
Luego se convierte esa variable a un factor ordenado, lo que es útil para análisis y visualizaciones en orden lógico (por ejemplo, del nivel más bajo al más alto).
Una forma de cerciorarse de que esta bien recodificado, es aplicar un select
de las variables (sin convertirla en objeto).
|> select(educ, educ_nivel) |> head(5) casen
educ educ_nivel
1 6 Media
2 1 Sin educación
3 2 Básica
4 2 Básica
5 0 Sin educación
Una recodificación se puedo aplicar yautco (Ingereso autónomo corregido) en base los quintiles.
quantile(casen$yautcor, na.rm = TRUE)
0% 25% 50% 75% 100%
2083 250000 439167 700000 11518333
Una forma más sofisticada de pedir los deciles
quantile(casen$yautcor, probs = seq(0, 1, 0.1), na.rm = TRUE)
0% 10% 20% 30% 40% 50% 60%
2083.0 120000.0 200000.0 300000.0 400000.0 439167.0 500000.0
70% 80% 90% 100%
600000.0 804666.4 1205499.8 11518333.0
Se crea una nueva variable llamada decil_yautcor
, que clasifica a cada persona dentro del decil que le corresponde según su ingreso autónomo. Se usa cut()
junto con los puntos de corte entregados por quantile()
.
<- casen |>
casen mutate(
decil_yautcor = cut(
yautcor,breaks = quantile(yautcor, probs = seq(0, 1, 0.1), na.rm = TRUE),
include.lowest = TRUE,
labels = paste0("Decil ", 1:10)
) )
<- casen %>%
casen mutate(decil_yautcor2 = case_when(
<= 120000 ~ "decil1",
yautcor <= 200000 ~ "decil2",
yautcor <= 300000 ~ "decil3",
yautcor <= 400000 ~ "decil4",
yautcor <= 439167 ~ "decil5",
yautcor <= 500000 ~ "decil6",
yautcor <= 600000 ~ "decil7",
yautcor <= 804666.4 ~ "decil8",
yautcor <= 1205499.8 ~ "decil9",
yautcor <= 11518333 ~ "decil10",
yautcor TRUE ~ NA_character_
))
|> select(yautcor, decil_yautcor, decil_yautcor2) |>
casen head(5)
yautcor decil_yautcor decil_yautcor2
1 660000 Decil 8 decil8
2 NA <NA> <NA>
3 NA <NA> <NA>
4 416667 Decil 5 decil5
5 NA <NA> <NA>
4.2 Group_by y summarise: Transmitir la información
4.2.1 Variables númericas: Ingreso autónomo corregido (yautcor).
✏️ ¿Qué estamos haciendo aquí?
Estamos agrupando la base según la variablepueblos_indigenas
, que indica si una persona se identifica o no con un pueblo originario. Luego, dentro de cada grupo, calculamos el promedio de ingreso autónomo corregido (yautcor
).
El parámetrona.rm = TRUE
sirve para ignorar los datos perdidos (valoresNA
).
✅ ¡Y así de simple! Ya estamos haciendo análisis comparativo entre grupos.
|> group_by(pueblos_indigenas) |>
casen summarise(salario = mean(yautcor, na.rm = TRUE)) #Borrar valores perdidos.
# A tibble: 2 × 2
pueblos_indigenas salario
<int> <dbl>
1 0 617099.
2 1 465819.
✏️ ¿Y ahora qué hicimos?
Hemos agregado otra dimensión de análisis:sexo
. Ahora no solo vemos si hay diferencias entre personas indígenas y no indígenas, sino también dentro de cada grupo según si son hombres o mujeres.
Además, calculamos no solo el promedio, sino también la mediana, que es un excelente complemento, especialmente cuando hay ingresos muy extremos que distorsionan los promedios.
|> group_by(pueblos_indigenas, sexo) |> # Veámoslo con sexo.
casen summarise(salario_mean = mean(yautcor, na.rm = TRUE),
salaria_median = median(yautcor, na.rm = TRUE)) # Agregamos otro estadístico
# A tibble: 4 × 4
# Groups: pueblos_indigenas [2]
pueblos_indigenas sexo salario_mean salaria_median
<int> <int> <dbl> <dbl>
1 0 1 726241. 500000
2 0 2 497682. 390000
3 1 1 599336. 496666.
4 1 2 362819. 324576.
|> group_by(pueblos_indigenas, sexo) |> # Veámoslo con sexo.
casen summarise(salario_mean = mean(yautcor, na.rm = TRUE),
salario_median = median(yautcor, na.rm = TRUE)) |> # Agregamos otro estadístico
mutate(ratio = salario_mean/salario_median) #un ratio alto puede sugerir que dentro del grupo hay mucha dispersión o desigualdad
# A tibble: 4 × 5
# Groups: pueblos_indigenas [2]
pueblos_indigenas sexo salario_mean salario_median ratio
<int> <int> <dbl> <dbl> <dbl>
1 0 1 726241. 500000 1.45
2 0 2 497682. 390000 1.28
3 1 1 599336. 496666. 1.21
4 1 2 362819. 324576. 1.12
La mayor desigualdad relativa está en hombres no indígenas, donde el ingreso promedio supera en un 45% a la mediana. Esto indica la presencia de personas con ingresos muy altos dentro del grupo.
4.2.2 Variables categóricas
✏️ ¿Qué estamos haciendo?
Aquí creamos una tabla con frecuencias y porcentajes de nivel educativo (educ_nivel
) dentro de cada grupo (pueblos_indigenas
).
Luego, usamos DT::datatable()
para convertir la tabla en un formato interactivo, donde podemos ordenar, buscar y exportar la información.
library(DT) #Tabla dinámica
<- casen |>
casen_tabla filter(!is.na(educ_nivel)) |>
count(pueblos_indigenas, educ_nivel, name = "n") |>
group_by(pueblos_indigenas) |>
mutate(
total = sum(n),
porcentaje = round(100 * n / total, 1)
|>
) arrange(pueblos_indigenas, educ_nivel)
::datatable(casen_tabla) DT
Veamos cómo asegurarnos de que todos los niveles de educación aparezcan, incluso si un grupo no tiene personas en algún nivel.
<- casen |>
casen_tabla2 filter(!is.na(educ_nivel)) |>
count(pueblos_indigenas, educ_nivel, name = "n") |>
complete(pueblos_indigenas, educ_nivel, fill = list(n = 0)) |> # Completar el postgrado
group_by(pueblos_indigenas) |>
mutate(
total = sum(n),
porcentaje = round(100 * n / total, 1)
|>
) arrange(pueblos_indigenas, educ_nivel)
::datatable(casen_tabla2) DT
4.3 Encadenar las funciones
# Seleccionamos solo las variables necesarias para el análisis:
# - pueblos_indigenas: para identificar si una persona se reconoce indígena
# - sexo: para distinguir entre hombres y mujeres
# - yautcor: ingreso autónomo corregido, nuestra variable de interés numérica
<- casen |>
casen_tabla3 select(pueblos_indigenas, sexo, yautcor) |>
# Reemplazamos los valores codificados por etiquetas legibles.
# 0 será "No indígena" y 1 será "Indígena"
mutate(
pueblos_indigenas = case_when(
== 0 ~ "No indígena",
pueblos_indigenas == 1 ~ "Indígena",
pueblos_indigenas TRUE ~ NA_character_ # Por si hubiera algún valor extraño o NA
),
# Hacemos lo mismo con la variable sexo:
# 1 será "Hombre", 2 será "Mujer"
sexo = case_when(
== 1 ~ "Hombre",
sexo == 2 ~ "Mujer",
sexo TRUE ~ NA_character_
),
# Creamos una nueva variable que combine ambos grupos:
# Por ejemplo: "Indígena - Mujer", "No indígena - Hombre", etc.
colapsa = paste(pueblos_indigenas, sexo, sep = " - ")
|>
)
# Agrupamos por esta nueva variable combinada (colapsa)
group_by(colapsa) |>
# Calculamos los dos estadísticos principales:
# - El ingreso promedio (mean)
# - El ingreso mediano (median)
# Ignoramos los NA con `na.rm = TRUE`
summarise(
salario_mean = mean(yautcor, na.rm = TRUE),
salaria_median = median(yautcor, na.rm = TRUE),
.groups = "drop" # Para evitar que el resultado quede agrupado
)
::datatable(casen_tabla3) DT
4.4 Exportar resultados a Excel
Una vez que hemos creado una tabla limpia y legible, puede ser útil exportarla para compartir con otras personas, usarla en un informe o guardarla como respaldo. Aquí usaremos dos paquetes adicionales:
scales
: para formatear los números y eliminar la notación científica (por ejemplo, mostrar 599,336 en vez de 599336.4444444445).writexl
: para guardar la tabla directamente en formato.xlsx
(compatible con Excel).
# Cargamos las librerías necesarias
library(scales)
library(writexl)
# Usamos mutate() para formatear las columnas numéricas:
# 'comma()' agrega separadores de miles y elimina notación científica
# 'accuracy = 1' indica que redondearemos al número entero más cercano
<- casen_tabla3 |>
casen_tabla_excel mutate(
salario_mean = comma(salario_mean, accuracy = 1), # Ej: 1.234.567
salaria_median = comma(salaria_median, accuracy = 1) # Ej: 1.100.000
)
# Finalmente, guardamos la tabla en un archivo Excel
# Este se guarda dentro de la carpeta 'bbdd' con el nombre 'casen_tabla.xlsx'
write_xlsx(casen_tabla_excel, "bbdd/casen_tabla.xlsx")
5 Cierre
A partir de los análisis de la Encuesta CASEN, hemos recorrido los elementos fundamentales para comenzar a trabajar con datos en R. Si bien este fue solo un primer acercamiento, ya contamos con herramientas suficientes para importar, explorar, transformar, resumir y comunicar información de manera clara y reproducible.
Durante este recorrido, es importante distinguir:
R base nos ofrece funciones fundamentales para manipular datos (summary()
, read.csv()
, mean()
, etc.), pero muchas veces estas son limitadas en términos de legibilidad y eficiencia cuando trabajamos con grandes volúmenes de datos o flujos de trabajo complejos. Las librerías son herramientas externas.
Por eso, incorporamos librerías como:
tidyverse
, que nos permitió usar funciones más intuitivas (mutate
,select
,filter
,group_by
,summarise
), y trabajar de forma encadenada con el operador|>
.DT
, que transformó tablas estáticas en objetos interactivos.scales
ywritexl
, que nos ayudaron a mejorar la comunicación de resultados y a exportar datos en formatos más accesibles.