---
title: "Exposición y población en riesgo"
aliases:
- "/06-exposicion/"
---
Mapa de la **situación actual de exposición** ante el episodio de El Niño
**2026-27 en curso** (con pronóstico de primavera lluviosa e inundaciones para
Paraguay). Cruza las **zonas inundables** —definidas empíricamente por las
huellas de inundación de episodios pasados— con la **población**, los
**servicios de salud** y los **centros educativos**.
::: {.callout-note}
Este mapa responde "¿quién está expuesto?" combinando dónde se inunda (evidencia
satelital de 2016/2019/2024) con quién y qué hay allí. No predice el episodio
2026-27; muestra la exposición estructural que ese episodio pondría a prueba.
:::
## Tablero de exposición
```{python}
#| label: tablero
#| echo: false
import json
from IPython.display import HTML
r = json.load(open("datos/exposicion/resumen.json", encoding="utf-8"))
n, p, zonas = r["nacional"], r["departamentos_prioritarios"], r["zonas_riesgo"]
def card(titulo, filas, color):
lis = "".join(f"<div style='display:flex;justify-content:space-between;gap:1em'>"
f"<span>{k}</span><b>{v}</b></div>" for k, v in filas)
return (f"<div style='flex:1;min-width:230px;border-top:4px solid {color};background:#f7f9fa;"
f"padding:.8em 1em;border-radius:6px'><div style='font-weight:700;margin-bottom:.4em'>{titulo}</div>{lis}</div>")
zona_cards = "".join(card(
f"Expuestos · {zv['nombre']}",
[("Servicios de salud", f"{zv['salud_expuestos']}"),
("Centros educativos", f"{zv['escuelas_expuestos']}")], "#8a1c1c") for zv in zonas.values())
rg = r["en_riesgo"]
html = "<div style='display:flex;gap:1em;flex-wrap:wrap'>" + card(
"Paraguay (total)",
[("Población", f"{n['poblacion']:,}"), ("Servicios de salud", f"{n['salud']:,}"),
("Centros educativos", f"{n['escuelas']:,}")], "#A81C9A") + card(
"⚠ Dentro de la zona de inundación",
[("Población en riesgo", f"{rg['poblacion']:,}"), ("Servicios de salud", f"{rg['salud']:,}"),
("Centros educativos", f"{rg['escuelas']:,}"), ("Alumnos (matrícula)", f"{rg['matricula']:,}")],
"#8a1c1c") + card(
"Departamentos ribereños prioritarios",
[("Población", f"{p['poblacion']:,}"), ("Niñez (0-14)", f"{p['ninez']:,}"),
("Adultos mayores (65+)", f"{p['mayores']:,}"), ("Servicios de salud", f"{p['salud']:,}"),
("Centros educativos", f"{p['escuelas']:,}")], "#b26a00") + zona_cards + "</div>"
HTML(html)
```
*Población: proyección 2023 (COD-PS, UNFPA/DGEEC). Salud: registro oficial
MSPBS/DIGIES. Educación: registro oficial MEC (2014). Zona de riesgo: huellas
Sentinel-1 + buffer de 550 m.*
## Mapa
```{python}
#| label: mapa-exposicion
#| echo: false
import json, os
import folium
from folium.plugins import MarkerCluster, FastMarkerCluster
deps = json.load(open("datos/geo/departamentos-exposicion.geojson", encoding="utf-8"))
m = folium.Map(location=[-23.8, -58.0], zoom_start=6, tiles="cartodbpositron", control_scale=True)
# Popup con los datos oficiales del establecimiento
# (salud MSPBS: categoría/subtipo/distrito · educación MEC: matrícula/distrito)
CAMPOS_POP = [("matricula", "Matrícula"), ("categoria", "Categoría"),
("subtipo", "Subtipo"), ("distrito", "Distrito"), ("barrio", "Barrio"),
("instituciones", "Instituciones")]
def popup_html(p, prefijo=""):
filas = []
for k, lab in CAMPOS_POP:
if p.get(k) not in (None, ""):
v = f"{p['matricula']} alumnos ({p.get('matricula_anio', 's/f')})" if k == "matricula" else p[k]
filas.append(f"<br><small>{lab}: {v}</small>")
return f"<b>{prefijo}{p.get('nombre','')}</b><br><i>{p.get('tipo','')}</i>{''.join(filas)}"
# Coropleta de población por departamento
def color_pop(v):
v = v or 0
return ("#08519c" if v > 600000 else "#3182bd" if v > 300000 else
"#6baed6" if v > 150000 else "#bdd7e7" if v > 50000 else "#eff3ff")
def estilo(f):
p = f["properties"]
return {"fillColor": color_pop(p.get("pop_total")),
"color": "#c0392b" if p.get("prioritario") else "#888",
"weight": 1.8 if p.get("prioritario") else 0.6, "fillOpacity": 0.75}
folium.GeoJson(
deps, name="Población por departamento",
style_function=estilo,
tooltip=folium.GeoJsonTooltip(
fields=["shapeName", "pop_total", "n_salud", "n_escuelas",
"pop_riesgo", "salud_riesgo", "escuelas_riesgo", "matricula_riesgo"],
aliases=["Departamento:", "Población (total):", "Salud (total):", "Escuelas (total):",
"▸ Población EN RIESGO:", "▸ Salud en riesgo:", "▸ Escuelas en riesgo:",
"▸ Alumnos en riesgo:"], localize=True),
).add_to(m)
# Servicios de salud (cluster)
salud = json.load(open("datos/geo/salud-puntos.geojson", encoding="utf-8"))
mc = MarkerCluster(name=f"Servicios de salud ({len(salud['features'])})").add_to(m)
for f in salud["features"]:
lon, lat = f["geometry"]["coordinates"]
folium.CircleMarker([lat, lon], radius=3, color="#1b5e7a", fill=True, fill_opacity=0.8,
popup=folium.Popup(popup_html(f["properties"]), max_width=260)).add_to(mc)
# Zonas de riesgo de inundación (todas las zonas detectadas)
zona = json.load(open("datos/geo/zona-riesgo-inundacion.geojson", encoding="utf-8"))
folium.GeoJson(zona, name="Zonas de riesgo de inundación",
style_function=lambda f: {"fillColor": "#d1495b", "color": "#d1495b", "weight": 0, "fillOpacity": 0.5},
tooltip=folium.GeoJsonTooltip(fields=["zona"], aliases=["Zona de riesgo:"])
).add_to(m)
# Establecimientos expuestos dentro de la zona de riesgo
exp = json.load(open("datos/geo/expuestos-inundacion.geojson", encoding="utf-8"))
capa_exp = folium.FeatureGroup(name=f"Expuestos en zona de riesgo ({len(exp['features'])})").add_to(m)
col = {"salud": "#1b5e7a", "educacion": "#b26a00"}
for f in exp["features"]:
lon, lat = f["geometry"]["coordinates"]
pr = f["properties"]
folium.CircleMarker([lat, lon], radius=5, color=col.get(pr["clase"], "#555"),
fill=True, fill_color=col.get(pr["clase"], "#555"), fill_opacity=0.9, weight=1,
popup=folium.Popup(popup_html(pr, prefijo=f"[{pr['clase']}] "), max_width=260),
tooltip=pr["nombre"]).add_to(capa_exp)
# Actividad comercial (OSM): capa completa liviana (cluster), desactivada por defecto
if os.path.exists("datos/geo/comercio-puntos.geojson"):
com = json.load(open("datos/geo/comercio-puntos.geojson", encoding="utf-8"))
coords = [[f["geometry"]["coordinates"][1], f["geometry"]["coordinates"][0]] for f in com["features"]]
FastMarkerCluster(coords, name=f"Actividad comercial · OSM ({len(coords)})").add_to(m)
# Comercio EXPUESTO dentro de la zona de riesgo (individualizado)
if os.path.exists("datos/geo/comercio-expuesto.geojson"):
cexp = json.load(open("datos/geo/comercio-expuesto.geojson", encoding="utf-8"))
capa_com = folium.FeatureGroup(name=f"Comercio expuesto ({len(cexp['features'])})").add_to(m)
for f in cexp["features"]:
lon, lat = f["geometry"]["coordinates"]; p = f["properties"]
nom = p.get("nombre") or p.get("tipo")
folium.CircleMarker([lat, lon], radius=5, color="#00695c", fill=True, fill_color="#009688",
fill_opacity=0.9, weight=1, tooltip=nom,
popup=folium.Popup(f"<b>[comercio] {p.get('nombre','')}</b><br><small>{p.get('tipo')}</small>",
max_width=220)).add_to(capa_com)
# Costanera (defensa costera) — obra que modula el riesgo
if os.path.exists("datos/geo/costanera-asuncion.geojson"):
cost = json.load(open("datos/geo/costanera-asuncion.geojson", encoding="utf-8"))
folium.GeoJson(cost, name="Costanera (defensa costera)",
style_function=lambda f: {"color": "#7b2cbf", "weight": 4},
tooltip=folium.GeoJsonTooltip(fields=["nombre"], aliases=["Obra:"])).add_to(m)
# Franja baja NO inundada junto a la Costanera (análisis DEM, exploratorio)
if os.path.exists("datos/geo/protegido-costanera.geojson"):
prot = json.load(open("datos/geo/protegido-costanera.geojson", encoding="utf-8"))
folium.GeoJson(prot, name="Franja baja protegida (DEM · exploratorio)",
style_function=lambda f: {"fillColor": "#1a9850", "color": "#1a9850",
"weight": 0, "fillOpacity": 0.55}, show=False).add_to(m)
# Susceptibilidad a inundación PLUVIAL (modelo topográfico DEM) — distinta de la
# fluvial (río). Azul = donde la lluvia se acumula/concentra por el relieve.
if os.path.exists("datos/geo/susceptibilidad-pluvial-asuncion.geojson"):
plu = json.load(open("datos/geo/susceptibilidad-pluvial-asuncion.geojson", encoding="utf-8"))
col_plu = {"alta": "#2b8cbe", "media": "#a6bddb"}
folium.GeoJson(plu, name="Susceptibilidad pluvial (DEM · modelo)",
style_function=lambda f: {"fillColor": col_plu.get(f["properties"]["clase"], "#a6bddb"),
"color": col_plu.get(f["properties"]["clase"], "#a6bddb"),
"weight": 0, "fillOpacity": 0.6},
tooltip=folium.GeoJsonTooltip(fields=["clase", "area_km2"],
aliases=["Susceptibilidad pluvial:", "Área (km²):"]),
show=False).add_to(m)
folium.LayerControl(collapsed=False).add_to(m)
leyenda = """
<div style="position:fixed; bottom:26px; left:12px; z-index:9999; background:white;
padding:10px 12px; border:1px solid #ccc; border-radius:6px; font-size:12px; line-height:1.5;
box-shadow:0 1px 4px rgba(0,0,0,.2);">
<b>Población (departamento)</b><br>
<span style="color:#08519c">■</span> >600k
<span style="color:#6baed6">■</span> 150-300k
<span style="color:#eff3ff;text-shadow:0 0 1px #999">■</span> <50k<br>
<span style="color:#c0392b">▮</span> Departamento ribereño prioritario<br>
<span style="color:#d1495b">▮</span> Zona de riesgo de inundación (fluvial)<br>
<span style="color:#2b8cbe">▮</span> Susceptibilidad pluvial alta (DEM · modelo)<br>
<span style="color:#7b2cbf">▬</span> Costanera (defensa) ·
<span style="color:#1a9850">▮</span> Franja baja protegida (DEM)<br>
<span style="color:#1b5e7a">●</span> Salud ·
<span style="color:#b26a00">●</span> Educación ·
<span style="color:#009688">●</span> Actividad comercial (expuestos)
</div>"""
m.get_root().html.add_child(folium.Element(leyenda))
m
```
*Los **8.030 centros educativos** (MEC) se agregan por departamento (conteo en el
tooltip); los **1.056 servicios de salud** (MSPBS) y los **10.342 puntos de actividad
comercial** (OSM, capa activable) se muestran agrupados. Solo se dibujan individualmente
los **expuestos** en la zona de riesgo (24 escuelas, 7 servicios de salud, 73 comercios y
servicios). Nota: varias USF y
escuelas comparten predio (misma coordenada) y se cuentan como servicios distintos.
Acercá el mapa a Asunción para ver la zona de riesgo y los establecimientos expuestos.*
::: {.callout-tip}
## Descargas: establecimientos en riesgo (Excel)
Los establecimientos dentro de la zona de inundación, con ubicación, atributos y **el
nivel del río al que se inundan** (cada uno contado en una sola zona, sin doble conteo):
- **[⬇ escuelas_riesgo.xlsx](../datos/exposicion/escuelas_riesgo.xlsx)** — **24 escuelas**
(MEC): matrícula, tipo de gestión, zona y nivel del río.
- **[⬇ salud_riesgo.xlsx](../datos/exposicion/salud_riesgo.xlsx)** — **7 servicios de
salud** (MSPBS): categoría (6 USF + 1 hospital distrital), distrito, zona y nivel del río.
- **[⬇ comercio_riesgo.xlsx](../datos/exposicion/comercio_riesgo.xlsx)** — **73 comercios y
servicios** (OpenStreetMap): tipo, rubro y ubicación. Cota inferior (OSM subrepresenta el
comercio informal).
:::
## Cómo se define la exposición
- **Zona de riesgo de inundación:** unión de las huellas de inundación derivadas
de Sentinel-1 para 2015-16, 2018-19 y 2023-24 (ver
[mapa histórico](../amenazas/inundacion-fluvial/index.qmd)), más un **buffer de 550 m** para
incluir los barrios afectados adyacentes, no solo la lámina de agua.
- **Expuestos:** servicios de salud y centros educativos cuya ubicación cae
dentro de esa zona de riesgo.
- **Departamentos prioritarios:** los ocho de mayor exposición ribereña/agrícola
(Central, Concepción, San Pedro, Pdte. Hayes, Ñeembucú, Misiones, Itapúa, Alto
Paraná), usados como aproximación de exposición a escala nacional.
## Efecto de la Costanera (análisis de elevación / DEM)
Para empezar a considerar las **obras de defensa**, se incorporó el **modelo de
elevación Copernicus DEM (30 m)**. Hallazgos (sobre los bañados de Asunción):
| Terreno | Elevación (m s/mar) |
|---|---|
| Bañados inundados (huella observada) | mediana **56,8** · p90 **58,5** |
| Ciudad (tierra firme circundante) | ~60-65 |
| **Costanera** (terraplén de defensa) | mediana **58,8** → **+2 m** sobre el bañado |
Es decir: **los bañados son la tierra más baja** (por eso se inundan) y la
**Costanera es un terraplén elevado** por encima del nivel que alcanzó la
inundación observada — coherente con su función de defensa. En el mapa, la capa
*"Franja baja protegida (DEM)"* marca **7,9 km²** de terreno bajo (≤ 58,5 m) junto
a la Costanera que **no** figuran en la huella observada: candidatos a estar
protegidos por el terraplén.
::: {.vacio}
**Análisis exploratorio, no un modelo hidráulico.** (1) El DEM de 30 m no capta la
microtopografía ni los edificios de los bañados. (2) El umbral de inundación se
calibra con lo *observado* por satélite, no con una cota absoluta. (3) La "franja
protegida" puede deberse a la Costanera **o a otras causas** (desconexión
hidráulica, otras defensas). (4) Falta la **cota de coronamiento** de la Costanera
(MOPC/Municipalidad) y la conversión al **cero hidrométrico** del río para
cuantificar el nivel de protección. Sirve para *señalar* dónde mirar, no para
afirmar cuánto protege.
:::
## Susceptibilidad a inundación pluvial (modelo DEM)
Junto a la inundación **fluvial** (río), el mapa incluye una capa activable de
**susceptibilidad pluvial** —dónde el relieve favorece que la **lluvia** se acumule
o concentre, con independencia del río—. Se deriva del **Copernicus DEM (30 m)**
combinando el relleno de depresiones (encharcamiento), la acumulación de flujo y el
índice topográfico de humedad. El detalle de la evidencia (temporales documentados,
arroyos urbanos, vínculo con El Niño) está en
[Inundaciones pluviales](../amenazas/inundacion-pluvial/index.qmd).
```{python}
#| label: pluvial-exp
#| echo: false
import json, os
from IPython.display import Markdown
p = "datos/exposicion/pluvial_resumen.json"
if os.path.exists(p):
d = json.load(open(p, encoding="utf-8"))
md = (f"En el modelo, la susceptibilidad **alta** cubre ~**{d['km2_alta']} km²** "
f"en Asunción y el metro interior. Considerando un **corredor anegable de "
f"~{d['buffer_m']} m** en torno a esos fondos de valle (~{d['km2_corredor_100m']} km²), "
f"quedan expuestos aproximadamente **{d['poblacion']:,} habitantes** "
f"(Kontur), **{d['escuelas']} centros educativos** (MEC) y **{d['salud']} "
f"servicios de salud** (MSPBS).")
else:
md = "::: {.vacio}\nResumen de exposición pluvial pendiente de generar.\n:::"
Markdown(md)
```
::: {.vacio}
**Modelo topográfico, no evento observado ni estudio hidráulico.** El DEM de 30 m
identifica *lows* a escala de barrio; no capta la red de desagües pluviales ni el
anegamiento a escala de calle. La exposición se cuenta en un corredor de ~100 m
alrededor de los fondos de valle (la inundación pluvial se extiende lateralmente),
por lo que es orientativa. Donde la susceptibilidad pluvial se solapa con la huella
fluvial, **ambas amenazas se combinan**.
:::
## Fuentes
- Población (total por departamento): **COD-PS 2023** (UNFPA/DGEEC), CC BY-IGO
[@codps_pry].
- Población **en riesgo** (dentro de la zona de inundación): **Kontur Population
2023** (hexágonos H3 ~400 m), CC BY [@kontur_pop]. Se cuenta la población de los
hexágonos cuyo centroide cae en la zona de riesgo.
- Servicios de salud: **registro oficial del MSPBS/DIGIES** (establecimientos
georreferenciados, 1.056 con categoría oficial) [@mspbs_datos].
- Centros educativos: **registro oficial del MEC** (datos.mec.gov.py, período 2014),
georreferenciado y con **matrícula** por establecimiento [@mec_datos].
- Departamentos: **geoBoundaries** [@geoboundaries_py].
- Zonas inundables: derivadas de **Sentinel-1** en este repositorio.
- **Costanera** y vialidad: **OpenStreetMap** (Overpass) [@osm].
- **Actividad comercial:** **OpenStreetMap** (`shop=*` + mercados, vía Overpass) [@osm].
Cota inferior: OSM subrepresenta el comercio informal y los barrios sin mapear.
- **Elevación del terreno:** **Copernicus DEM GLO-30** (30 m) [@copernicus_dem].
- **Susceptibilidad pluvial:** modelo topográfico propio sobre el Copernicus DEM
(relleno de depresiones + acumulación de flujo + índice de humedad topográfica)
[@copernicus_dem]. Evidencia de eventos y teleconexión ENOS-lluvia en
[Inundaciones pluviales](../amenazas/inundacion-pluvial/index.qmd).
## Vacíos y límites
Hay **zonas de riesgo detalladas** para Asunción, Pilar/Ñeembucú, Alberdi y Villa
Hayes. La exposición fuera de Asunción es **baja** (0-2 establecimientos por zona):
las zonas de anegamiento son los canales del río —no los centros urbanos— y la
cobertura de OSM en pueblos chicos es escasa; muchos establecimientos quedan
apenas fuera del buffer. Es una cota inferior, no la exposición real.
::: {.vacio}
- **Educación** usa el registro **oficial del MEC** con matrícula, pero del
**período 2014** (último publicado en el portal); la ubicación es representativa
aunque desactualizada.
- **Salud** usa el registro **oficial del MSPBS/DIGIES** (georreferenciado, con
categoría oficial). No incluye camas ni dotación de personal por establecimiento.
- **Obras de defensa no ajustadas:** el mapa se basa en huellas históricas de
inundación y **no descuenta la protección** de obras como la **Costanera**
(Norte/Sur) o el drenaje reciente. Donde hay defensa nueva, la exposición puede
estar **sobreestimada**. La Costanera se muestra como capa de contexto, no como
reductor cuantificado (haría falta la cota de protección del MOPC/Municipalidad).
La huella de 2019 ya es posterior a la Costanera Norte (~2013); la Costanera Sur
y obras 2020s no están reflejadas.
- **Concepción** quedó pendiente: no hay cobertura de Sentinel-1 RTC reciente
(2022-2024) sobre el norte para derivar su zona de anegamiento con este método.
- La exposición **no** incorpora aún **vulnerabilidad social** (asentamientos
informales, pobreza), que agravaría el riesgo en las mismas zonas.
:::