Visión general
El proyecto sigue un pipeline ETL en cuatro fases, implementado íntegramente en R. El flujo transforma datos electorales en bruto procedentes de múltiples fuentes heterogéneas (CSV, Excel, .px, APIs) en una base de datos relacional PostgreSQL normalizada y en formatos descargables (Parquet, SQLite, CSV).
Fase 1: Datos en bruto (data-raw/)
Contiene los ficheros originales tal como se obtienen de cada fuente: CSV, RDS, Excel (.xls/.xlsx), ficheros estadísticos PX-WEB (.px) y datos descargados vía API. Cada comunidad autónoma tiene su propia carpeta en data-raw/hechos/.
Además incluye:
fechas_elecciones.csv— Fechas de todas las convocatorias electorales.codigos_territorios/— Códigos de secciones censales (INE/Infoelectoral), circunscripciones sub-provinciales y correspondencias municipio–circunscripción.nombres_municipios.csv— Nomenclátor de municipios del INE.representantes/— Escaños asignados y representantes electos por provincia y municipio.partidos_recodes.xlsx— Tabla maestra de recodificación/agrupación de partidos.
Consulta cómo poblar data-raw/ en la guía: Restaurar data-raw/
Fase 2: Generación de datos intermedios (R/01-generate-data/)
Transforma los datos en bruto en tablas intermedias estandarizadas (formato RDS) en data-processed/.
Dimensiones
| Script | Salida | Descripción |
|---|---|---|
dimensiones/elecciones/fechas-elecciones-format.R | tablas-finales/dimensiones/elecciones | Normaliza fechas en español, codifica tipo de elección, genera slug |
dimensiones/territorios/territorios.R | tablas-finales/dimensiones/territorios | Construye jerarquía territorial (CCAA → provincia → circunscripción → municipio → distrito → sección) con parent_id |
dimensiones/partidos/sync-partidos.R | tablas-finales/dimensiones/partidos, partidos_recode | Sincroniza partidos desde partidos_recodes.xlsx |
dimensiones/partidos/new-partidos.R | data-processed/partidos_recodes_pending.xlsx | Detecta partidos nuevos sin recodificación asignada |
Hechos (por comunidad autónoma)
Cada subcarpeta de R/01-generate-data/hechos/ contiene scripts específicos que generan dos ficheros RDS por autonomía en data-processed/hechos/:
info.rds— Resumen territorial: censo, participación, votos válidos, blancos, nulos.votos.rds— Votos por partido y territorio.
| Carpeta | Ámbito | Scripts principales |
|---|---|---|
00-congreso/ | Congreso (nacional) | sauron_formats.R → format_provincias.R, format_municipios.R, format_secciones.R |
01-andalucia/ | Andalucía | 00_fetch-nomenclators.R → 01-06_fetch-*.R → 07-format-data.R |
02-aragon/ | Aragón | 01_format-info.R, 02_format-votos.R |
03-asturias/ | Asturias | 00_get-nomenclator-sadei.R, 01_format-data.R |
04-baleares/ | Baleares | format.R |
05-canarias/ | Canarias | 00_download-data-parcan.R, format.R |
07-cyl/ | Castilla y León | format.R |
09-catalunya/ | Cataluña | 01_format-data.R |
10-comunidad-valenciana/ | C. Valenciana | format.R |
13-comunidad-madrid/ | C. de Madrid | format.R |
Fase 3: Limpieza y unión (R/02-clean-and-bind/)
Une todos los datos intermedios de las distintas autonomías en las tablas finales del modelo relacional.
01-partidos-sin-id.R
Detecta partidos que aparecen en los datos de votos pero aún no tienen un ID asignado en la dimensión partidos. Los incorpora automáticamente a tablas-finales/dimensiones/partidos.
02-bind-hechos.R
Script principal que:
- Lee todos los
info.rdsyvotos.rdsdedata-processed/hechos/. - Asigna
partido_idpor matching case-insensitive de(siglas, denominacion). Falla si quedan votos sin partido asignado. - Incorpora
nrepresentantes(escaños asignables) yrepresentantes(electos) desde las funciones auxiliares deutils.R. - Agrupa votos a granularidad
(eleccion_id, territorio_id, partido_id). - Genera las tablas finales:
tablas-finales/hechos/info.rds→resumen_territorialtablas-finales/hechos/votos.rds→votos_territoriales
Validación
Antes de la carga en BD, se ejecutan validaciones automáticas (R/tests/):
validate_data_processed.R: valida estructura, tipos, unicidad y coherencia lógica de los datos intermedios.validate_tablas_finales.R: valida dimensiones (estructura, FKs, unicidad) y hechos (FKs a elecciones/territorios/partidos, rangos numéricos).
Fase 4: Carga y exportación
Carga a PostgreSQL (R/03-writedb/write-db.R)
- Ejecuta las validaciones de dimensiones y hechos.
- Trunca todas las tablas con
RESTART IDENTITY. - Recarga dimensiones y hechos completos con
DBI::dbWriteTable(..., append = TRUE).
Exportación a formatos descargables (R/04-export/export-descargas.R)
Genera tres formatos en descargas/:
| Formato | Ruta | Descripción |
|---|---|---|
| Parquet | descargas/parquet/dimensiones/, descargas/parquet/hechos/ | Tablas individuales en formato columnar eficiente |
| SQLite | descargas/eleccionesdb.sqlite | Esquema relacional completo con PKs, FKs, UNIQUE e índices |
| CSV planos | descargas/csv/resumen_territorial.csv, descargas/csv/votos_territoriales.csv | Tablas de hechos con todas las dimensiones pre-joineadas |
Flujo típico desde cero
- Configurar
.envcon credenciales de PostgreSQL. - Crear esquema en BD ejecutando
R/db_schema.sql. - Preparar ficheros de datos en
data-raw/. - Ejecutar scripts de generación por autonomía (
R/01-generate-data/hechos/*). - Ejecutar scripts de dimensiones (elecciones, territorios, partidos).
- Detectar y asignar partidos nuevos.
- Unir hechos finales (
R/02-clean-and-bind/). - Validar.
- Cargar en BD (
R/03-writedb/write-db.R). - Exportar (
R/04-export/export-descargas.R).
Flujo para nuevas elecciones
- Incorporar nuevos ficheros de resultados en
data-raw/hechos/<autonomía>/. - Ejecutar el script de formato correspondiente en
R/01-generate-data/hechos/<autonomía>/. - Ejecutar
new-partidos.Rpara detectar nuevos partidos → revisarpartidos_recodes_pending.xlsx. - Incorporar nuevos partidos a
partidos_recodes.xlsxy ejecutarsync_partidos(). - Ejecutar
01-partidos-sin-id.Ry02-bind-hechos.R. - Validar, cargar en BD y exportar.