{"id":50588761,"url":"https://github.com/cortega26/chile-hub","last_synced_at":"2026-06-30T02:00:32.823Z","repository":{"id":361506472,"uuid":"1254613303","full_name":"cortega26/chile-hub","owner":"cortega26","description":"Datos públicos de Chile curados, normalizados y validados: geografía, demografía, economía, salud, educación y distritos electorales. Listos para consumir en una línea de código con Polars, DuckDB, SQLite y Excel.","archived":false,"fork":false,"pushed_at":"2026-06-29T13:15:54.000Z","size":101782,"stargazers_count":64,"open_issues_count":1,"forks_count":9,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-29T13:25:18.899Z","etag":null,"topics":["chile","data-engineering","datasets","datos","datos-abiertos","duckdb","open-data","parquet","polars","public-data"],"latest_commit_sha":null,"homepage":"https://tooltician.com/chile-hub/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cortega26.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"cortega26","buy_me_a_coffee":"cortega26"}},"created_at":"2026-05-30T19:42:14.000Z","updated_at":"2026-06-29T11:46:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cortega26/chile-hub","commit_stats":null,"previous_names":["cortega26/chile-hub"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/cortega26/chile-hub","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortega26%2Fchile-hub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortega26%2Fchile-hub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortega26%2Fchile-hub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortega26%2Fchile-hub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cortega26","download_url":"https://codeload.github.com/cortega26/chile-hub/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cortega26%2Fchile-hub/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34949234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chile","data-engineering","datasets","datos","datos-abiertos","duckdb","open-data","parquet","polars","public-data"],"created_at":"2026-06-05T08:30:58.306Z","updated_at":"2026-06-30T02:00:32.815Z","avatar_url":"https://github.com/cortega26.png","language":"Python","funding_links":["https://github.com/sponsors/cortega26","https://buymeacoffee.com/cortega26"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003ch1\u003e\n  \u003cimg\n    src=\"https://rawcdn.githack.com/twitter/twemoji/v14.0.2/assets/svg/1f1e8-1f1f1.svg\"\n    alt=\"🇨🇱\"\n    width=\"39\"\n    align=\"absmiddle\"\n  \u003e\n  chile-hub\n\u003c/h1\u003e\n\n\u003cp\u003e\u003cstrong\u003eDatos públicos de Chile, curados y listos para análisis en una línea de código.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eEl hub de datos abiertos de Chile — parte del ecosistema Tooltician.\u003c/em\u003e\u003c/p\u003e\n\n[![Parte de Tooltician](https://img.shields.io/badge/Parte_de-Tooltician.com-6C47FF?v=2)](https://tooltician.com)\n[![CI/CD](https://github.com/cortega26/chile-hub/actions/workflows/pipeline-check.yml/badge.svg)](https://github.com/cortega26/chile-hub/actions)\n[![PyPI version](https://img.shields.io/pypi/v/chile-hub.svg)](https://pypi.org/project/chile-hub/)\n[![PyPI downloads](https://img.shields.io/pypi/dm/chile-hub.svg)](https://pypi.org/project/chile-hub/)\n[![Coverage](https://img.shields.io/endpoint?url=https://tooltician.com/chile-hub/data/normalized/coverage_badge.json)](https://tooltician.com/chile-hub/data/normalized/hub_status.json)\n[![Data](https://img.shields.io/endpoint?url=https://tooltician.com/chile-hub/data/normalized/freshness_badge.json)](https://tooltician.com/chile-hub/data/normalized/hub_health.json)\n[![License: MIT](https://img.shields.io/badge/Code%20License-MIT-blue.svg)](LICENSE)\n[![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-3776AB.svg?style=flat\u0026logo=python\u0026logoColor=white)]()\n[![Formats](https://img.shields.io/badge/Formats-Parquet%20%7C%20DuckDB%20%7C%20SQLite%20%7C%20JSON%20%7C%20Excel-orange.svg)]()\n[![Datasets](https://img.shields.io/badge/Datasets-15%20capas-16a34a.svg)]()\n[![Comunas](https://img.shields.io/badge/Comunas-346-8b5cf6.svg)]()\n\n\u003cp\u003e\n  \u003ca href=\"#-instalar-y-usar-en-segundos\"\u003eInstalación\u003c/a\u003e ·\n  \u003ca href=\"#las-15-capas-de-datos\"\u003eCapas\u003c/a\u003e ·\n  \u003ca href=\"#arquitectura-del-pipeline\"\u003eArquitectura\u003c/a\u003e ·\n  \u003ca href=\"#cli-de-referencia\"\u003eCLI\u003c/a\u003e ·\n  \u003ca href=\"#fuentes-licencias-y-reúso\"\u003eLicencias\u003c/a\u003e\n\u003c/p\u003e\n\n\u003c/div\u003e\n\n---\n\n## ⚡ Instalar y usar en segundos\n\n```bash\npip install chile-hub\n```\n\n```python\nfrom chile_hub import ChileHub\n\nhub = ChileHub()\ncomunas = hub.load_polars(\"comunas\")          # 346 comunas como DataFrame\nindicadores = hub.load_polars(\"indicadores\")  # Serie histórica UF, Dólar, Euro, UTM, IPC\n\n# Cruce territorial garantizado — códigos CUT siempre VARCHAR\ncenso = hub.load_polars(\"censo_comunal\")\ndf = comunas.join(censo, on=\"codigo_comuna\")\nprint(df.head())\n```\n\nLa primera ejecución descarga automáticamente el bundle validado desde GitHub Releases, verifica su integridad SHA256 y lo deja en cache local. A partir de ahí, todo corre contra el cache. También puedes administrarlo explícitamente:\n\n```bash\nchile-hub cache update     # Forzar descarga del bundle más reciente\nchile-hub cache status     # Ubicación y estado del cache local\nchile-hub cache clear      # Liberar espacio\n```\n\n\u003e **Variante para desarrolladores del pipeline:** `pip install chile-hub[pipeline]` agrega DuckDB, Pandas, XlsxWriter y curl_cffi para ejecutar el pipeline completo de extracción y build. La instalación mínima solo incluye Polars, PyArrow, requests y platformdirs — suficiente para consumir datos.\n\n\u003e [!NOTE]\n\u003e **chile-hub** no busca \"tener todos los datos de Chile\". Busca **reducir drásticamente el costo técnico** de encontrar, limpiar, validar, cruzar y consumir datasets geográficos, demográficos, electorales y económicos críticos de Chile.\n\nEn la práctica, sirve para responder preguntas comunes sin rehacer limpieza base:\n\n- ¿Cómo cruzo mi base de clientes, escuelas o centros de salud con comunas oficiales sin perder ceros en los códigos?\n- ¿Qué comunas concentran población censada, establecimientos públicos o indicadores urbanos?\n- ¿Cómo llevo datos oficiales a Polars, DuckDB, SQLite, Excel o CI sin depender de enlaces cambiantes?\n\n---\n\n## ¿Por qué existe?\n\nTrabajar con datos públicos chilenos implica enfrentar los mismos obstáculos una y otra vez:\n\n| ❌ Sin chile-hub | ✅ Con chile-hub |\n|:---|:---|\n| Enlaces rotos y APIs inconsistentes | Pipeline automatizado con fallbacks y verificación de integridad |\n| Planillas Excel deformes con celdas combinadas | Parquet, DuckDB y JSON listos para producción |\n| Códigos CUT que pierden ceros al leerse como `int` | CUT garantizados como `VARCHAR` de largo fijo (`\"01101\"`) |\n| Nombres de comunas imposibles de cruzar (_Ñuñoa_ vs _Nunoa_) | Columna `nombre_comuna_clean` normalizada para cruces exactos |\n| Cero trazabilidad sobre origen y vigencia del dato | Metadatos con fuente, fecha de extracción, licencia y modo |\n\nchile-hub empaqueta esas decisiones en una capa reproducible: extrae desde fuentes oficiales, normaliza schemas, valida reglas territoriales y publica artefactos listos para consumo local o CI/CD.\n\n---\n\n## ¿Qué entrega chile-hub?\n\n\u003ctable\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n**Curado y validado**\nCada capa pasa por validaciones automáticas de integridad referencial, cardinalidad exacta (346 comunas) y formato de códigos territoriales. El pipeline **falla ruidosamente** antes de publicar datos corruptos.\n\n\u003c/td\u003e\u003ctd\u003e\n\n**Cruzable por diseño**\nTodos los datasets se vinculan mediante códigos CUT (`codigo_comuna`, `codigo_provincia`, `codigo_region`). Una sola clave une demografía, salud, educación, finanzas municipales, indicadores urbanos y distritos electorales.\n\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n**Múltiples formatos**\nParquet para analítica de alto rendimiento, DuckDB para consultas SQL locales, SQLite para aplicaciones embebidas, JSON para pipelines y Excel para usuarios de planillas. Todos generados desde la misma fuente.\n\n\u003c/td\u003e\u003ctd\u003e\n\n**Trazabilidad total**\nCada artefacto incluye: fuente original, fecha de extracción, modo (en vivo/respaldo), hash SHA256, licencia y estatus de redistribución. Sabes exactamente qué estás consumiendo.\n\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n**Una línea de código**\n```python\nfrom chile_hub import ChileHub\n\nhub = ChileHub()\ndf = hub.load_polars(\"comunas\")\n```\n\n\u003c/td\u003e\u003ctd\u003e\n\n**CI/CD transparente**\nPipeline determinista en GitHub Actions: extracción → build → verificación → tests → pruebas de humo. Todo reproducible en local con `make refresh`.\n\n\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n---\n\n## Las 15 capas de datos\n\n| # | Capa | Registros | Modo | Fuente | Licencia | Actualización |\n|:--:|:---|:---|:--:|:---|:---|:--:|\n| 1 | **Regiones** | 16 | 🟢 live | BCN ArcGIS | CC BY | — |\n| 2 | **Provincias** | 56 | 🟢 live | BCN ArcGIS | CC BY | — |\n| 3 | **Comunas** | 346 | 🟢 live | BCN ArcGIS | CC BY | — |\n| 4 | **Comunas Enriquecidas** | 346 | 🟢 live | BCN + INE | CC BY | — |\n| 5 | **Indicadores Económicos** | Serie histórica | 🟢 live | BCCh / mindicador.cl | Libre c/cita | Diaria |\n| 6 | **Censo Comunal 2024** | 346 | 🟢 live | INE | CC BY 4.0 | Decenal |\n| 7 | **Censo Hogares y Viviendas** | 346 | 🟢 live | INE | CC BY 4.0 | Decenal |\n| 8 | **Establecimientos de Salud** | ~5 600 | 🟢 live | MINSAL / datos.gob.cl | CC0 | Mensual |\n| 9 | **Distritos Electorales** | 346 | 🟢 live | BCN / Ley 20.840 | CC0 | — |\n| 10 | **Establecimientos Educacionales** | ~12 900 | 🟢 live | MINEDUC | CC BY 3.0 CL | Anual |\n| 11 | **Finanzas Municipales** | fallback curado | 🟡 fallback | SINIM / SUBDERE | Revisión términos | Anual |\n| 12 | **Resultados Educacionales** | fallback curado | 🟡 fallback | MINEDUC | CC BY 3.0 CL | Anual |\n| 13 | **Indicadores Urbanos SIEDU** | cobertura parcial | 🟡 fallback | INE / SIEDU | Datos abiertos INE | Anual |\n| 14 | **Perfil Territorial Comunal** | 346 | 🟡 fallback | chile-hub derivado | Fuentes abiertas | Derivada |\n| 15 | **Empresas (RES)** | ~1 570 000 | 🟢 live | Min. Economía / datos.gob.cl | CC-BY 3.0 CL | Mensual |\n\n\u003e **🟢 live**: datos extraídos directamente desde la fuente oficial en cada ejecución del pipeline.\n\u003e **🟡 fallback**: datos servidos desde un respaldo curado mientras se completa la extracción en vivo.\n\u003e Para auditar el estado exacto de cada capa: `chile-hub provenance` y `chile-hub health`.\n\n\u003e **Todas las capas se vinculan por `codigo_comuna`**, el Código Único Territorial de 5 caracteres definido por SUBDERE.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eVer schema completo de cada capa\u003c/b\u003e\u003c/summary\u003e\n\n\u003cbr\u003e\n\n**1. regiones** — 16 regiones político-administrativas\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `codigo_region` | `VARCHAR(2)` | `\"01\"` |\n| `nombre_region` | `VARCHAR` | `\"Tarapacá\"` |\n\n**2. provincias** — 56 provincias con referencia a su región\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `codigo_region` | `VARCHAR(2)` | `\"01\"` |\n| `nombre_region` | `VARCHAR` | `\"Tarapacá\"` |\n| `codigo_provincia` | `VARCHAR(3)` | `\"011\"` |\n| `nombre_provincia` | `VARCHAR` | `\"Iquique\"` |\n\n**3. comunas** — 346 comunas con nombres oficiales y limpios, coordenadas y población\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `codigo_comuna` | `VARCHAR(5)` | `\"01101\"` |\n| `nombre_comuna` | `VARCHAR` | `\"Iquique\"` |\n| `nombre_comuna_clean` | `VARCHAR` | `\"iquique\"` |\n| `codigo_provincia` | `VARCHAR(3)` | `\"011\"` |\n| `codigo_region` | `VARCHAR(2)` | `\"01\"` |\n| `nombre_region` | `VARCHAR` | `\"Tarapacá\"` |\n| `latitud_cabecera` | `DOUBLE` | `-20.2138` |\n| `longitud_cabecera` | `DOUBLE` | `-70.1508` |\n| `poblacion_estimada` | `INTEGER` | `223400` |\n\n**4. comunas_enriquecidas** — Comunas con coordenadas de cabecera y población estimada INE\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `codigo_comuna` | `VARCHAR(5)` | `\"01101\"` |\n| `nombre_comuna` | `VARCHAR` | `\"Iquique\"` |\n| `nombre_comuna_clean` | `VARCHAR` | `\"iquique\"` |\n| `codigo_provincia` | `VARCHAR(3)` | `\"011\"` |\n| `codigo_region` | `VARCHAR(2)` | `\"01\"` |\n| `latitud_cabecera` | `DOUBLE` | `-20.2138` |\n| `longitud_cabecera` | `DOUBLE` | `-70.1508` |\n| `poblacion_estimada` | `INTEGER` | `223400` |\n\n**5. indicadores** — Serie de indicadores económicos diarios (UF, Dólar, Euro, UTM, IPC)\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `fecha` | `DATE` | `2026-05-30` |\n| `codigo_indicador` | `VARCHAR` | `\"uf\"` |\n| `valor` | `DOUBLE` | `39420.50` |\n\n**6. censo_comunal** — Población por sexo y 5 tramos de edad para las 346 comunas\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `codigo_region` | `VARCHAR(2)` | `\"01\"` |\n| `codigo_provincia` | `VARCHAR(3)` | `\"011\"` |\n| `codigo_comuna` | `VARCHAR(5)` | `\"01101\"` |\n| `nombre_comuna` | `VARCHAR` | `\"Iquique\"` |\n| `poblacion_censada` | `INTEGER` | `223400` |\n| `hombres` / `mujeres` | `INTEGER` | `111200` / `112200` |\n| `razon_hombre_mujer` | `DOUBLE` | `99.11` |\n| `poblacion_0_14` … `poblacion_65_mas` | `INTEGER` | 5 tramos etarios |\n\n**7. censo_hogares_viviendas** — Viviendas, hogares y promedio de personas por hogar\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `codigo_comuna` | `VARCHAR(5)` | `\"01101\"` |\n| `viviendas_censadas` | `INTEGER` | `85000` |\n| `viviendas_particulares_ocupadas` | `INTEGER` | `75000` |\n| `viviendas_colectivas` | `INTEGER` | `200` |\n| `hogares_censados` | `INTEGER` | `73000` |\n| `promedio_personas_hogar` | `DOUBLE` | `3.06` |\n\n**8. establecimientos_salud** — Directorio nacional de recintos de salud (~5 600)\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `codigo_establecimiento` | `VARCHAR` | `\"101101\"` |\n| `nombre_establecimiento` | `VARCHAR` | `\"Hospital Dr. Ernesto Torres Galdames\"` |\n| `tipo_establecimiento` | `VARCHAR` | `\"Hospital\"` |\n| `nivel_atencion` | `VARCHAR` | `\"Alta Complejidad\"` |\n| `codigo_comuna` | `VARCHAR(5)` | `\"01101\"` |\n| `tiene_servicio_urgencia` | `VARCHAR` | `\"SI\"` / `\"NO\"` |\n| `latitud` / `longitud` | `DOUBLE` | Coordenadas geográficas |\n| `estado_funcionamiento` | `VARCHAR` | `\"Vigente\"` |\n\n**9. distritos_electorales** — Mapeo de comunas a distritos y circunscripciones\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `codigo_comuna` | `VARCHAR(5)` | `\"13114\"` |\n| `nombre_comuna` | `VARCHAR` | `\"Las Condes\"` |\n| `distrito_electoral` | `VARCHAR` | `\"11\"` |\n| `circunscripcion_senatorial` | `VARCHAR` | `\"7\"` |\n\n**10. establecimientos_educacionales** — Directorio de colegios y liceos (~12 900)\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `rbd` | `VARCHAR` | `\"1\"` |\n| `dv_rbd` | `VARCHAR` | `\"4\"` |\n| `nombre_establecimiento` | `VARCHAR` | `\"Liceo Abate Molina\"` |\n| `codigo_comuna` | `VARCHAR(5)` | `\"07101\"` |\n| `dependencia_administrativa` | `VARCHAR` | `\"Municipal\"` |\n| `latitud` / `longitud` | `DOUBLE` | Coordenadas geográficas |\n| `estado_funcionamiento` | `VARCHAR` | `\"Vigente\"` |\n\n**11. finanzas_municipales** — Indicadores financieros municipales anuales\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `anio` | `INTEGER` | `2024` |\n| `codigo_comuna` | `VARCHAR(5)` | `\"13101\"` |\n| `ingresos_totales` / `gastos_totales` | `DOUBLE` | `245000000000.0` |\n| `ingresos_propios_permanentes` | `DOUBLE` | `162000000000.0` |\n| `fondo_comun_municipal` | `DOUBLE` | `39000000000.0` |\n\n**12. resultados_educacionales** — Métricas educacionales agregadas por comuna/año\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `anio` | `INTEGER` | `2024` |\n| `codigo_comuna` | `VARCHAR(5)` | `\"13101\"` |\n| `matricula_total` | `INTEGER` | `122000` |\n| `asistencia_promedio` | `DOUBLE` | `86.2` |\n| `tasa_aprobacion` / `tasa_retiro` | `DOUBLE` | `91.4` / `4.5` |\n\n**13. indicadores_urbanos_siedu** — Indicadores urbanos en formato largo\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `anio` | `INTEGER` | `2024` |\n| `codigo_comuna` | `VARCHAR(5)` | `\"13101\"` |\n| `codigo_indicador` | `VARCHAR` | `\"siedu_acceso_areas_verdes\"` |\n| `categoria` | `VARCHAR` | `\"Espacio publico\"` |\n| `valor` / `unidad` | `DOUBLE` / `VARCHAR` | `71.4` / `\"porcentaje\"` |\n\n**14. perfil_territorial_comunal** — Perfil derivado con una fila por comuna\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `codigo_comuna` | `VARCHAR(5)` | `\"13101\"` |\n| `poblacion_censada` | `INTEGER` | `223400` |\n| `establecimientos_salud_total` | `INTEGER` | `140` |\n| `establecimientos_educacionales_total` | `INTEGER` | `410` |\n| `distrito_electoral` | `VARCHAR` | `\"10\"` |\n\n**15. empresas** — Registro de Empresas y Sociedades (RES) con RUT, razón social, tipo societario y comuna\n| Columna | Tipo | Ejemplo |\n|:---|:---|:---|\n| `rut` | `VARCHAR` | `\"76286049-K\"` |\n| `razon_social` | `VARCHAR` | `\"COMERCIALIZADORA EJEMPLO SPA\"` |\n| `codigo_sociedad` | `VARCHAR` | `\"SPA\"` |\n| `capital` | `INTEGER` | `5000000` |\n| `fecha_actuacion` | `DATE` | `2020-06-15` |\n| `anio` | `INTEGER` | `2020` |\n| `comuna_tributaria` | `VARCHAR` | `\"SANTIAGO\"` |\n| `region_tributaria` | `VARCHAR` | `\"13\"` |\n\n\u003c/details\u003e\n\n---\n\n## Guía de uso\n\n### Consumir datos (instalación desde PyPI)\n\n```bash\npip install chile-hub\n```\n\n```python\nfrom chile_hub import ChileHub\n\nhub = ChileHub()\n\n# Catálogo de capas disponibles\nprint(hub.list_datasets())\n\n# Cargar cualquier capa como Polars DataFrame\ncomunas = hub.load_polars(\"comunas\")\ncenso = hub.load_polars(\"censo_comunal\")\nsalud = hub.load_polars(\"establecimientos_salud\")\n\n# Cruce garantizado: códigos CUT son VARCHAR, no int\ndf = comunas.join(censo, on=\"codigo_comuna\")\nprint(df.head())\n\n# Salud operativa del hub\nprint(hub.health())\n```\n\nLa primera ejecución descarga el bundle validado desde GitHub Releases, verifica\nsu integridad SHA256 y lo deja en cache local. También puedes prepararlo explícitamente:\n\n```bash\nchile-hub cache update     # Descargar el bundle más reciente\nchile-hub cache status     # Ver ubicación y estado del cache\nchile-hub cache clear      # Liberar espacio en disco\n```\n\n### Consultas SQL con DuckDB\n\n```sql\n-- Top 10 comunas por población censada\nSELECT nombre_comuna, poblacion_censada, hombres, mujeres\nFROM 'data/normalized/censo_comunal.parquet'\nORDER BY poblacion_censada DESC\nLIMIT 10;\n\n-- Cruce territorial: comunas × distritos electorales\nSELECT c.nombre_comuna, c.nombre_region,\n       e.distrito_electoral, e.circunscripcion_senatorial\nFROM 'data/normalized/comunas.parquet' c\nJOIN 'data/normalized/distritos_electorales.parquet' e\n  ON c.codigo_comuna = e.codigo_comuna\nWHERE c.nombre_region = 'Valparaíso';\n```\n\n### Usar en scripts y producción\n\n```python\nimport polars as pl\n\ncomunas = pl.read_parquet(\"data/normalized/comunas.parquet\")\ncenso = pl.read_parquet(\"data/normalized/censo_comunal.parquet\")\n\n# Cruce garantizado: códigos CUT son VARCHAR, no int\ndf = comunas.join(censo, on=\"codigo_comuna\")\nprint(df.head())\n```\n\n\u003e **Versionado:** Para entornos productivos, fija la versión exacta en `requirements.txt`:\n\u003e ```\n\u003e chile-hub==1.15.0\n\u003e ```\n\u003e El bundle de datos se publica con cada release. La API del módulo `ChileHub` sigue\n\u003e versionado semántico: cambios de interfaz pública solo en _major releases_.\n\n### Desarrollo local del pipeline\n\nSi necesitas ejecutar el pipeline de extracción y build en tu máquina:\n\n```bash\ngit clone https://github.com/cortega26/chile-hub.git\ncd chile-hub\nmake bootstrap          # Crea .venv, instala dependencias + Playwright\nmake refresh            # extract → build → verify → test → pruebas de humo\n```\n\n\u003e Usa `pip install chile-hub[pipeline]` si quieres las dependencias completas del pipeline\n\u003e (DuckDB, Pandas, XlsxWriter, curl_cffi) pero sin clonar el repositorio.\n\n### Casos de uso listos para copiar\n\n**1. Ranking comunal con Censo 2024**\n\n```python\nfrom chile_hub import ChileHub\n\nhub = ChileHub()\ncomunas = hub.load_polars(\"comunas\")\ncenso = hub.load_polars(\"censo_comunal\")\n\nranking = (\n    comunas.join(censo, on=\"codigo_comuna\")\n    .select(\"codigo_comuna\", \"nombre_comuna\", \"nombre_region\", \"poblacion_censada\")\n    .sort(\"poblacion_censada\", descending=True)\n    .head(10)\n)\nprint(ranking)\n```\n\n**2. Últimos indicadores económicos disponibles**\n\n```python\nfrom chile_hub import ChileHub\n\ndf = ChileHub().load_polars(\"indicadores\")\nultimos = (\n    df.sort(\"fecha\", descending=True)\n    .group_by(\"codigo_indicador\")\n    .first()\n    .select(\"codigo_indicador\", \"fecha\", \"valor\")\n    .sort(\"codigo_indicador\")\n)\nprint(ultimos)\n```\n\n**3. Salud y educación por comuna**\n\n```python\nfrom chile_hub import ChileHub\n\nhub = ChileHub()\nsalud = hub.load_polars(\"establecimientos_salud\")\neducacion = hub.load_polars(\"establecimientos_educacionales\")\n\nsalud_por_comuna = salud.group_by(\"codigo_comuna\").len(\"establecimientos_salud\")\neducacion_por_comuna = educacion.group_by(\"codigo_comuna\").len(\"establecimientos_educacionales\")\n\nresumen = (\n    hub.load_polars(\"comunas\")\n    .join(salud_por_comuna, on=\"codigo_comuna\", how=\"left\")\n    .join(educacion_por_comuna, on=\"codigo_comuna\", how=\"left\")\n    .fill_null(0)\n    .select(\"codigo_comuna\", \"nombre_comuna\", \"establecimientos_salud\", \"establecimientos_educacionales\")\n)\nprint(resumen.head())\n```\n\n### API Python compacta\n\n| API | Uso |\n|:---|:---|\n| `ChileHub()` | Inicializa el helper; descarga y verifica el bundle si no hay cache local. |\n| `ChileHub(data_dir=\"data/normalized\")` | Usa artefactos locales generados por el pipeline. |\n| `hub.list_datasets()` | Lista los nombres canónicos disponibles para `load_polars()`. |\n| `hub.load_polars(\"comunas\")` | Carga una capa como `polars.DataFrame` desde Parquet. |\n| `hub.summary()` / `hub.summary_table()` | Resume modo de fuente, filas, validación, frescura y warnings. |\n| `hub.health()` / `hub.status()` | Reporta salud operativa para personas y CI/CD. |\n| `hub.redistribution()` | Expone estado legal de reúso y atribución por dataset. |\n| `hub.provenance()` | Muestra fuente, URL, modo de extracción y timestamps. |\n| `chile-hub cache update/status/clear` | Administra el cache local del bundle publicado. |\n\n---\n\n## Arquitectura del Pipeline\n\nEl pipeline es **lineal, determinista y estricto**: si una validación falla, el build se cancela antes de publicar datos corruptos.\n\n```mermaid\nflowchart TB\n    classDef extract fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0f172a;\n    classDef stage fill:#ecfeff,stroke:#0891b2,stroke-width:2px,color:#0f172a;\n    classDef build fill:#fef9c3,stroke:#ca8a04,stroke-width:2px,color:#0f172a;\n    classDef verify fill:#f0fdf4,stroke:#16a34a,stroke-width:2px,color:#0f172a;\n    classDef test fill:#fae8ff,stroke:#c084fc,stroke-width:2px,color:#0f172a;\n    classDef publish fill:#ffe4e6,stroke:#f43f5e,stroke-width:2px,color:#0f172a;\n\n    subgraph EXTRACT[\"1. EXTRACT - fuentes oficiales\"]\n        direction TB\n        X1[\"Territorio\u003cbr/\u003eBCN / SERVEL\"]:::extract\n        X2[\"Demografía 2024\u003cbr/\u003eINE\"]:::extract\n        X3[\"Servicios públicos\u003cbr/\u003eMINSAL / MINEDUC\"]:::extract\n        X4[\"Economía\u003cbr/\u003eBCCh / SINIM / RES\"]:::extract\n        X5[\"Indicadores urbanos\u003cbr/\u003eSIEDU\"]:::extract\n    end\n\n    S[\"data/staging/\u003cbr/\u003eCSV + metadata.json\"]:::stage\n    B[\"2. BUILD\u003cbr/\u003ebuild_dev_db.py\"]:::build\n    N[\"data/normalized/\u003cbr/\u003eartefactos publicables\"]:::stage\n    V[\"3. VERIFY\u003cbr/\u003everify_pipeline.py\"]:::verify\n    T[\"4. TEST\u003cbr/\u003epytest\"]:::test\n    L[\"5. SMOKE + PUBLISH\u003cbr/\u003elanding + bundle\"]:::publish\n\n    X1 --\u003e S\n    X2 --\u003e S\n    X3 --\u003e S\n    X4 --\u003e S\n    X5 --\u003e S\n    S --\u003e B --\u003e N --\u003e V --\u003e T --\u003e L\n```\n\n\u003e [!IMPORTANT]\n\u003e **Invariante crítica:** El pipeline aborta si la cardinalidad de comunas ≠ 346, si los códigos CUT pierden el formato `VARCHAR`, o si alguna regla de negocio se rompe. **Nunca** se publican datos corruptos.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eExtractores incluidos en el paso 1\u003c/b\u003e\u003c/summary\u003e\n\n| Dominio | Extractores |\n|:---|:---|\n| Territorio | `subdere_extractor.py`, `electoral_extractor.py` |\n| Demografía | `censo_extractor.py`, `censo_hogares_viviendas_extractor.py` |\n| Servicios públicos | `salud_extractor.py`, `mineduc_establecimientos_extractor.py`, `mineduc_resultados_extractor.py` |\n| Economía | `bcentral_extractor.py`, `sinim_finanzas_extractor.py`, `res_extractor.py` |\n| Indicadores urbanos | `siedu_extractor.py` |\n\n\u003c/details\u003e\n\n---\n\n## Modelo de Datos — Códigos CUT\n\nEl valor central de chile-hub es que **todas las capas se vinculan jerárquicamente** mediante los Códigos Únicos Territoriales (CUT) de SUBDERE/INE:\n\n```mermaid\nflowchart TB\n    R[\"Territorio base\u003cbr/\u003e\u003cb\u003eREGIONES\u003c/b\u003e\u003cbr/\u003ecodigo_region\"]\n    P[\"\u003cb\u003ePROVINCIAS\u003c/b\u003e\u003cbr/\u003ecodigo_provincia + codigo_region\"]\n    C[\"\u003cb\u003eCOMUNAS\u003c/b\u003e\u003cbr/\u003ecodigo_comuna + codigo_provincia + codigo_region\"]\n    L[\"Capas comunales\u003cbr/\u003ecodigo_comuna\u003cbr/\u003ecenso · hogares · salud\u003cbr/\u003eeducación · distritos · enriquecimiento\"]\n\n    R --\u003e P --\u003e C --\u003e L\n```\n\n| Grupo | Clave principal | Capas |\n|:---|:---|:---|\n| Territorio base | `codigo_region`, `codigo_provincia`, `codigo_comuna` | `regiones`, `provincias`, `comunas` |\n| Capas comunales | `codigo_comuna` | `comunas_enriquecidas`, `censo_comunal`, `censo_hogares_viviendas`, `establecimientos_salud`, `establecimientos_educacionales`, `distritos_electorales` |\n| Series nacionales | `fecha`, `codigo_indicador` | `indicadores` |\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eVer schema completo con PK/FK\u003c/b\u003e\u003c/summary\u003e\n\n```mermaid\nerDiagram\n    REGIONES {\n        VARCHAR codigo_region PK \"Ej: '01' (Tarapacá)\"\n        VARCHAR nombre_region\n    }\n    PROVINCIAS {\n        VARCHAR codigo_provincia PK \"Ej: '011' (Iquique)\"\n        VARCHAR codigo_region FK\n        VARCHAR nombre_provincia\n    }\n    COMUNAS {\n        VARCHAR codigo_comuna PK \"Ej: '01101' (Iquique)\"\n        VARCHAR codigo_provincia FK\n        VARCHAR codigo_region FK\n        VARCHAR nombre_comuna\n        VARCHAR nombre_comuna_clean \"Ej: 'iquique' (sin tildes)\"\n    }\n    COMUNAS_ENRIQUECIDAS {\n        VARCHAR codigo_comuna PK\n        VARCHAR nombre_comuna\n        DOUBLE latitud_cabecera\n        DOUBLE longitud_cabecera\n        INTEGER poblacion_estimada\n    }\n    CENSO_COMUNAL {\n        VARCHAR codigo_comuna PK\n        INTEGER poblacion_censada\n        INTEGER hombres\n        INTEGER mujeres\n        INTEGER poblacion_0_14\n    }\n    CENSO_HOGARES_VIVIENDAS {\n        VARCHAR codigo_comuna PK\n        INTEGER viviendas_censadas\n        INTEGER hogares_censados\n        DOUBLE promedio_personas_hogar\n    }\n    ESTABLECIMIENTOS_SALUD {\n        VARCHAR codigo_establecimiento PK\n        VARCHAR codigo_comuna FK\n        VARCHAR nombre_establecimiento\n        VARCHAR tipo_establecimiento\n    }\n    DISTRITOS_ELECTORALES {\n        VARCHAR codigo_comuna PK\n        VARCHAR distrito_electoral\n        VARCHAR circunscripcion_senatorial\n    }\n    ESTABLECIMIENTOS_EDUCACIONALES {\n        VARCHAR rbd PK \"Rol Base de Datos\"\n        VARCHAR codigo_comuna FK\n        VARCHAR nombre_establecimiento\n    }\n    INDICADORES {\n        DATE fecha PK\n        VARCHAR codigo_indicador PK \"Ej: 'uf', 'dolar'\"\n        DOUBLE valor\n    }\n\n    REGIONES ||--o{ PROVINCIAS : \"contiene\"\n    PROVINCIAS ||--o{ COMUNAS : \"contiene\"\n    COMUNAS ||--|| COMUNAS_ENRIQUECIDAS : \"enriquece\"\n    COMUNAS ||--o| CENSO_COMUNAL : \"demografía\"\n    COMUNAS ||--o| CENSO_HOGARES_VIVIENDAS : \"hogares\"\n    COMUNAS ||--o{ ESTABLECIMIENTOS_SALUD : \"salud\"\n    COMUNAS ||--o{ ESTABLECIMIENTOS_EDUCACIONALES : \"educación\"\n    COMUNAS ||--o| DISTRITOS_ELECTORALES : \"electoral\"\n```\n\n\u003c/details\u003e\n\n---\n\n## Formatos de salida\n\nCada ejecución del pipeline genera en `data/normalized/`:\n\n| Tipo | Archivo | Uso |\n|:---|:---|:---|\n| **Base de datos** | `chile_data.duckdb` | Analítica local de alto rendimiento |\n| **Base de datos** | `chile_data.db` | SQLite para aplicaciones embebidas |\n| **Intercambio** | `chile_data_latest.xlsx` | Excel multipestaña (códigos CUT como texto) |\n| **Intercambio** | `*.parquet` por capa | Polars / Pandas / DuckDB |\n| **Intercambio** | `*.json` por capa | Pipelines y automatización |\n| **Metadatos** | `artifact_manifest.json` | Catálogo físico con SHA256 y tamaños |\n| **Metadatos** | `hub_health.json` / `.md` | Reporte de salud operativa |\n| **Metadatos** | `dataset_status.json` | Estado machine-readable por dataset |\n| **Metadatos** | `dataset_changelog.json` | Deltas de filas, campos, fuente y validación |\n| **Metadatos** | `dataset_catalog.json` / `.md` | Catálogo con schemas y ejemplos |\n| **Metadatos** | `redistribution_report.json` / `.md` | Estado legal de reúso por dataset |\n| **Metadatos** | `provenance_report.json` / `.md` | Trazabilidad de origen y marcas de tiempo |\n| **Bundle** | `chile-hub-publishable-bundle.zip` | Paquete público con verificación SHA256 |\n\n---\n\n## CLI de referencia\n\nEl paquete instala el comando `chile-hub` en el `PATH`. Todos los subcomandos\nfuncionan tanto desde PyPI como desde el entorno de desarrollo.\n\n### Inspección y consulta\n\n| Comando | Descripción |\n|:---|:---|\n| `chile-hub list` | Lista todos los datasets registrados |\n| `chile-hub version` | Muestra la versión instalada del paquete |\n| `chile-hub cache status` | Muestra ubicación y estado del cache local |\n| `chile-hub cache update` | Descarga y verifica el bundle publicado |\n| `chile-hub cache clear` | Elimina el cache local |\n| `chile-hub show \u003ccapa\u003e` | Schema y metadatos detallados de una capa |\n| `chile-hub path \u003ccapa\u003e --output parquet` | Ruta física al archivo de una capa |\n| `chile-hub example \u003ccapa\u003e --kind duckdb` | Receta de consumo lista para copiar y pegar |\n| `chile-hub overview` | Resumen general del build y estado actual |\n| `chile-hub inventory` | Archivos en `data/normalized/` con tamaños y hashes |\n\n### Calidad, salud y auditoría\n\n| Comando | Descripción |\n|:---|:---|\n| `chile-hub health` | Reporte consolidado de salud del hub |\n| `chile-hub freshness-audit` | Auditoría de frescura contra el reloj actual |\n| `chile-hub runtime-status` | Salud registrada + vigencia en vivo |\n| `chile-hub top-issue` | Capa con mayor degradación operativa |\n| `chile-hub drift` | Desvíos, fallbacks activos y regresiones |\n| `chile-hub status` | JSON ultraliviano para CI/CD |\n| `chile-hub dataset-status` | Estado detallado machine-readable por dataset |\n| `chile-hub dataset-changelog` | Cambios entre el build actual y el metadata anterior |\n\n### Distribución e integridad\n\n| Comando | Descripción |\n|:---|:---|\n| `chile-hub bundle` | Metadata consolidada en un solo JSON |\n| `chile-hub redistribution` | Reporte legal de reúso por capa |\n| `chile-hub provenance` | URLs de origen y métodos de extracción |\n| `chile-hub verify-package` | Instrucción de verificación de integridad del ZIP |\n\n\u003e En entorno de desarrollo, usa `python -m chile_hub` o `python -m src.chile_hub`\n\u003e como alternativa al comando `chile-hub` si el paquete no está instalado en modo editable.\n\n---\n\n## Desarrollo local\n\nEsta sección es para contribuidores que necesitan ejecutar el pipeline completo\nde extracción, build y verificación en su máquina. Si solo necesitas consumir\nlos datos, usa `pip install chile-hub` (ver [Guía de uso](#guía-de-uso)).\n\n```bash\n# Entorno\nmake bootstrap          # Crea .venv, instala dependencias + Playwright\nmake doctor             # Verifica versión de Python y dependencias críticas\n\n# Pipeline completo\nmake refresh            # extract → build → verify → test → landing\n\n# Pasos individuales\nmake extract            # Ejecuta los extractores → data/staging/\nmake build              # Compila artefactos → data/normalized/\nmake verify             # Verifica integridad (SHA256, conteos, schema)\nmake test               # pytest (lee data/normalized/, no corre el pipeline)\nmake coverage           # pytest + cobertura de src/ (term-missing + coverage.xml)\nmake verify-landing     # Pruebas de humo de landing page con Playwright\n\n# Tests\n./.venv/bin/pytest -v\n./.venv/bin/pytest --cov=src --cov-report=term-missing --cov-report=xml\n./.venv/bin/pytest tests/test_chile_hub.py::ChileHubTests::test_load_polars -v\n```\n\n---\n\n## Fuentes, licencias y reúso\n\n### Semáforo de redistribución\n\n| Color | Estado | Acción |\n|:---:|:---|:---|\n| 🟢 `open-attribution` | CC BY, CC0 o equivalente | Se incluye en el bundle público |\n| 🟡 `public-api-review-terms` | API pública sin licencia explícita | Se distribuye tras verificar el origen primario |\n| 🔴 `restricted` | Derechos de autor, Ley 19.628 | **Nunca** se integra al bundle público |\n\n### Licencia del proyecto\n\nEl código Python se distribuye bajo **[MIT](LICENSE)**. Los datasets conservan\nlas licencias, permisos y requisitos de atribución de sus fuentes oficiales.\nConsulta [DATA_LICENSES.md](DATA_LICENSES.md), `chile-hub redistribution` y\n`chile-hub provenance` antes de redistribuir artefactos derivados.\n\n---\n\n## Próximos pasos\n\nEl roadmap actual prioriza crecer en usabilidad y confianza antes que agregar más capas.\n\n| Horizonte | Foco | Resultado esperado |\n|:---|:---|:---|\n| Now | Ejemplos, notebooks, errores claros y referencia API | Usuarios cargan y cruzan datos sin leer el pipeline completo. |\n| Next | Contratos de schema, source readiness y criterios públicos | Contribuidores proponen datasets con reglas claras y verificables. |\n| Later | Nuevas capas solo si pasan criterios de inclusión | El catálogo crece sin perder mantenibilidad ni claridad legal. |\n\n\u003e La especificación completa del producto está en [`docs/product-spec.md`](./docs/product-spec.md).\n\u003e Los criterios públicos para solicitar nuevas capas están en [`docs/dataset-inclusion-criteria.md`](./docs/dataset-inclusion-criteria.md).\n\u003e El estado de la última corrida se documenta en `data/normalized/pipeline_status.md` tras cada build.\n\n---\n\n## ¿Quieres contribuir?\n\nRevisa [`AGENTS.md`](./AGENTS.md) para entender la arquitectura, las reglas no negociables y el flujo de trabajo. El punto de partida rápido es [`SOURCE_OF_TRUTH.md`](./SOURCE_OF_TRUTH.md).\n\n**¿Encontraste un error o tienes un caso de uso?** Abre un [issue](https://github.com/cortega26/chile-hub/issues) — ayuda a priorizar el roadmap.\n\n\n\u003cdiv align=\"center\"\u003e\n\n**\u003cimg src=\"https://rawcdn.githack.com/twitter/twemoji/v14.0.2/assets/svg/1f1e8-1f1f1.svg\" alt=\"🇨🇱\" width=\"20\" align=\"absmiddle\"\u003e  Hecho con datos públicos chilenos, para quienes construyen sobre Chile.**\n\n\u003csub\u003eParte del [ecosistema Tooltician](https://tooltician.com) — datos públicos, interoperables y listos para IA.\u003c/sub\u003e\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcortega26%2Fchile-hub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcortega26%2Fchile-hub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcortega26%2Fchile-hub/lists"}