miércoles, 19 de octubre de 2022 From rOpenSci (https://ropensci.org/es/blog/2022/10/19/censo2017-one-year-after-es/). Except where otherwise noted, content on this site is licensed under the CC-BY license.
Este artículo trata sobre los usos sorprendentes que he observado y las preguntas que recibo sobre el paquete R censo2017, una herramienta para acceder a los datos del censo chileno de 2017, que he recibido desde que fue revisado por pares a través de rOpenSci hace un año. El artículo original sobre el paquete no cubría los diferentes ejemplos que presento aquí, incluyendo una versión Python del paquete R.
Hace tres años, tuve que realizar una tarea que me exigía extraer los datos de un software sólo para Windows en formato DVD, lo que se hizo muy complicado.
Necesitaba acceder a los archivos REDATAM y obtener unos resúmenes de población con un software específico para ese formato. Para mi sorpresa, la tarea fue increíblemente difícil, y exporté los datos a SQL para una extracción de datos más accesible.
Lo que inicialmente organicé en PostgreSQL, terminó siendo organizado en una base de datos local (embebida), que es más conveniente para los usuarios finales y puede instalarse con dos líneas de código.
Instalación en R:
remotes::install_github("ropensci/censo2017")
censo2017::censo_descargar()
Instalación en Python:
pip install git+https://github.com/pachadotdev/censo2017python.git#egg=censo2017
import censo2017
censo2017.descargar()
Podemos utilizar los datos del censo para determinar dónde son comunes las viviendas precarias, lo que nos permite obtener ideas valiosas para la política pública. Esto es algo que nunca contemplé cuando hice el software.
¿Qué tipo de información sobre la vivienda podemos buscar en el censo? Para simplificar
vamos a explorar la variable p01
, que podemos consultar en la tabla
variables_codificación
, la cual creé para organizar mi trabajo.
library(censo2017)
library(dplyr)
con <- censo_conectar()
tbl(con, "variables") %>%
filter(variable == "p01") %>%
collect() %>%
kable()
tabla | variable | descripcion | tipo | rango |
---|---|---|---|---|
viviendas | p01 | Tipo de Vivienda | integer | 1 - 10 |
tbl(con, "variables_codificacion") %>%
filter(variable == "p01") %>%
select(valor, descripcion) %>%
collect() %>%
kable()
La variable se refiere al “Tipo de Vivienda” y contiene diez valores numéricos que significan:
valor | descripcion |
---|---|
1 | Casa |
2 | Departamento en Edificio |
3 | Vivienda Tradicional Indígena (Ruka, Pae Pae u Otras) |
4 | Pieza en Casa Antigua o en Conventillo |
5 | Mediagua, Mejora, Rancho o Choza |
6 | Móvil (Carpa, Casa Rodante o Similar) |
7 | Otro Tipo de Vivienda Particular |
8 | Vivienda Colectiva |
9 | Operativo Personas en Tránsito (No Es Vivienda) |
10 | Operativo Calle (No Es Vivienda) |
11 | Valor Perdido |
0 | No Aplica |
En este ejemplo, considero las viviendas codificadas como 5 (Mediagua, Mejora, Rancho o Choza) como subestándar. Debido a la organización de los datos del censo, para obtener la proporción de estos tipos de vivienda por región, necesitamos
p01
y contar el número de unidades.Por ejemplo, si queremos ver la 14ava región específicamente, una forma de hacerlo podría ser:
tbl(con, "zonas") %>%
mutate(region = str_sub(geocodigo, 1, 2)) %>%
filter(region == 14) %>%
inner_join(tbl(con, "viviendas")) %>%
group_by(p01) %>%
count() %>%
collect() %>%
kable()
p01 | n |
---|---|
1 | 144081 |
2 | 4793 |
3 | 44 |
4 | 494 |
5 | 2187 |
6 | 35 |
7 | 1875 |
8 | 467 |
9 | 6 |
10 | 8 |
Podemos mejorar esta salida con una unión opcional y un paso para extraer los porcentajes:
tbl(con, "zonas") %>%
mutate(region = str_sub(geocodigo, 1, 2)) %>%
filter(region == "14") %>%
inner_join(tbl(con, "viviendas")) %>%
group_by(p01) %>%
count() %>%
left_join(
tbl(con, "variables_codificacion") %>%
filter(variable == "p01") %>%
select(p01 = valor, p01_desc = descripcion)
) %>%
select(p01, p01_desc, n) %>%
arrange(-n) %>%
ungroup() %>%
mutate(p = round(100 * n / sum(n), 2)) %>%
collect() %>%
kable()
p01 | p01_desc | n | p |
---|---|---|---|
1 | Casa | 144081 | 93.57 |
2 | Departamento en Edificio | 4793 | 3.11 |
5 | Mediagua, Mejora, Rancho o Choza | 2187 | 1.42 |
7 | Otro Tipo de Vivienda Particular | 1875 | 1.22 |
4 | Pieza en Casa Antigua o en Conventillo | 494 | 0.32 |
8 | Vivienda Colectiva | 467 | 0.30 |
3 | Vivienda Tradicional Indígena (Ruka, Pae Pae u Otras) | 44 | 0.03 |
6 | Móvil (Carpa, Casa Rodante o Similar) | 35 | 0.02 |
10 | Operativo Calle (No Es Vivienda) | 8 | 0.01 |
9 | Operativo Personas en Tránsito (No Es Vivienda) | 6 | 0.00 |
Para la 14ava región, la calidad de la vivienda no parece ser un problema. ¿Y si nos preguntamos por el número de personas que viven en cada uno de estos tipos de unidades? Esto requeriría pasos adicionales para unir a las personas con los hogares y los hogares con las viviendas.
tbl(con, "zonas") %>%
mutate(region = str_sub(geocodigo, 1, 2)) %>%
filter(region == "14") %>%
inner_join(tbl(con, "viviendas")) %>%
inner_join(tbl(con, "hogares")) %>%
inner_join(tbl(con, "personas")) %>%
group_by(p01) %>%
count() %>%
left_join(
tbl(con, "variables_codificacion") %>%
filter(variable == "p01") %>%
select(p01 = valor, p01_desc = descripcion)
) %>%
select(p01, p01_desc, n) %>%
arrange(-n) %>%
ungroup() %>%
mutate(p = round(100 * n / sum(n), 2)) %>%
collect() %>%
kable()
p01 | p01_desc | n | p |
---|---|---|---|
1 | Casa | 359343 | 93.38 |
2 | Departamento en Edificio | 9139 | 2.37 |
8 | Vivienda Colectiva | 7905 | 2.05 |
5 | Mediagua, Mejora, Rancho o Choza | 3980 | 1.03 |
7 | Otro Tipo de Vivienda Particular | 3008 | 0.78 |
4 | Pieza en Casa Antigua o en Conventillo | 727 | 0.19 |
9 | Operativo Personas en Tránsito (No Es Vivienda) | 494 | 0.13 |
3 | Vivienda Tradicional Indígena (Ruka, Pae Pae u Otras) | 96 | 0.02 |
10 | Operativo Calle (No Es Vivienda) | 84 | 0.02 |
6 | Móvil (Carpa, Casa Rodante o Similar) | 61 | 0.02 |
¿Cómo se compara el resultado anterior con el de la capital (13ava región)?
tbl(con, "zonas") %>%
mutate(region = str_sub(geocodigo, 1, 2)) %>%
filter(region == "13") %>%
inner_join(tbl(con, "viviendas")) %>%
inner_join(tbl(con, "hogares")) %>%
inner_join(tbl(con, "personas")) %>%
group_by(p01) %>%
count() %>%
left_join(
tbl(con, "variables_codificacion") %>%
filter(variable == "p01") %>%
select(p01 = valor, p01_desc = descripcion)
) %>%
select(p01, p01_desc, n) %>%
arrange(-n) %>%
ungroup() %>%
mutate(p = round(100 * n / sum(n), 2)) %>%
collect() %>%
kable()
p01 | p01_desc | n | p |
---|---|---|---|
1 | Casa | 5265416 | 74.03 |
2 | Departamento en Edificio | 1613157 | 22.68 |
8 | Vivienda Colectiva | 78763 | 1.11 |
4 | Pieza en Casa Antigua o en Conventillo | 72142 | 1.01 |
5 | Mediagua, Mejora, Rancho o Choza | 52710 | 0.74 |
7 | Otro Tipo de Vivienda Particular | 17335 | 0.24 |
9 | Operativo Personas en Tránsito (No Es Vivienda) | 9113 | 0.13 |
10 | Operativo Calle (No Es Vivienda) | 2740 | 0.04 |
3 | Vivienda Tradicional Indígena (Ruka, Pae Pae u Otras) | 865 | 0.01 |
6 | Móvil (Carpa, Casa Rodante o Similar) | 567 | 0.01 |
De los datos resumidos anteriores podemos ver que en la capital, 52.710 personas viven en viviendas precarias (Mediagua, Mejora, Rancho o Choza).
No debemos olvidar cerrar la conexión de base de datos.
censo_desconectar()
La motivación de este ejemplo es mostrar que el objetivo de organizar los datos del censo no era promover R, sino mostrar algunos de los beneficios de tener los datos organizados en un formato abierto, independientemente del lenguaje de programación utilizado para el análisis. Para mí es más fácil completar este ejemplo en R, pero quería incluir a las personas que utilizan estos datos del censo con Python.
La variable para la fuente de agua es p05
. El análisis es muy similar
al anterior, y empezamos por ver su descripción. Este ejemplo
es relevante, ya que permite cuantificar el número de personas que podrían
estar expuestas a agua contaminada en una zona determinada.
import censo2017
import duckdb
con = duckdb.connect(database = censo2017.archivo_sql())
con.execute("SELECT * FROM variables_codificacion WHERE variable = 'p05'").df()
## tabla variable valor descripcion
## 0 viviendas p05 1 Red Pública
## 1 viviendas p05 2 Pozo o Noria
## 2 viviendas p05 3 Camión Aljibe
## 3 viviendas p05 4 Río, Vertiente, Estero, Canal, Lago, Etc.
## 4 viviendas p05 99 Valor Perdido
## 5 viviendas p05 98 No Aplica
Utilizando esta variable, podemos conocer el número de personas para cada fuente de agua de la misma manera que en el caso anterior.
con.execute("""
SELECT "p05", "p05_desc", "n",
ROUND((100.0 * "n") / SUM("n") OVER (), CAST(ROUND(2.0, 0) AS INTEGER)) AS "p"
FROM (
SELECT "LHS"."p05" AS "p05", "n", "p05_desc"
FROM (
SELECT "p05", COUNT(*) AS "n"
FROM (
SELECT *, "LHS"."hogar_ref_id" AS "hogar_ref_id"
FROM (
SELECT *, "LHS"."vivienda_ref_id" AS "vivienda_ref_id"
FROM (
SELECT *, "LHS"."zonaloc_ref_id" AS "zonaloc_ref_id"
FROM (
SELECT *
FROM (
SELECT *, SUBSTR("geocodigo", 1, 2) AS "region"
FROM "zonas"
) "q01"
WHERE ("region" = '14')
) "LHS"
INNER JOIN "viviendas" AS "RHS"
ON ("LHS"."zonaloc_ref_id" = "RHS"."zonaloc_ref_id")
) "LHS"
INNER JOIN "hogares" AS "RHS"
ON ("LHS"."vivienda_ref_id" = "RHS"."vivienda_ref_id")
) "LHS"
INNER JOIN "personas" AS "RHS"
ON ("LHS"."hogar_ref_id" = "RHS"."hogar_ref_id")
) "q02"
GROUP BY "p05"
) "LHS"
LEFT JOIN (
SELECT "valor" AS "p05", "descripcion" AS "p05_desc"
FROM "variables_codificacion"
WHERE ("variable" = 'p05')
) "RHS"
ON ("LHS"."p05" = "RHS"."p05")
) "q03"
ORDER BY -"n"
""").df()
## p05 p05_desc n p
## 0 1 Red Pública 299464 77.82
## 1 4 Río, Vertiente, Estero, Canal, Lago, Etc. 38796 10.08
## 2 2 Pozo o Noria 32150 8.35
## 3 98 No Aplica 8483 2.20
## 4 3 Camión Aljibe 3558 0.92
## 5 99 Valor Perdido 2386 0.62
Aquí vemos que para la 14ava región, el 22,18% de la población no
tiene acceso a la red pública de agua corriente. La ventaja de este
enfoque es que aquí utilizamos SQL puro para la consulta, que funcionaría en
cualquier lenguaje en el que podamos pasar consultas SQL. La desventaja es que no
tenemos una herramienta como dplyr
y está la necesidad de aprender la sintaxis SQL.
No debemos olvidar cerrar la conexión a la base de datos.
con.close()
Los ejemplos mostrados aquí se han simplificado. La mayoría de las consultas que recibo son sobre resúmenes de datos a nivel subcomunitario, por ejemplo cómo contar las ocurrencias de una variable categórica en un barrio, como hicimos en nuestro ejemplo de acceso al agua (es decir, pozo o red pública). Usando censo2017 podemos extraer información útil para las políticas públicas basada en la evidencia cuando se trata, por ejemplo, de priorizar las decisiones presupuestarias.