El incendio urbano no depende del clima de forma directa, así que esta página no usa proyecciones CMIP6. La incertidumbre principal del índice no es climática sino metodológica: los pesos son un juicio (3.4.a). El «escenario» que se evalúa es, entonces, qué tanto cambia el orden de las manzanas si los pesos cambian.
Método¶
Se simulan miles de vectores de pesos con una distribución de Dirichlet centrada en los pesos base. La concentración fijada hace que cada peso varíe de forma moderada alrededor de su valor base (no se exploran pesos extremos). Para cada simulación se recalcula el índice y el orden de las manzanas, y se resumen la variación del índice, el intervalo del rango de cada unidad y la probabilidad de estar entre las más altas.
Estabilidad del ranking¶
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from IPython.display import display
from sidro import exposicion, process
from sidro.analisis import indices, urbano
from sidro.config import parametros
from sidro.fetch import obtener_capa
edif = intentar(exposicion.edificaciones, mensaje="No se pudo construir la exposición de edificaciones")
inc = intentar(obtener_capa, "incidentes_incendio_urbano", mensaje="Sin incidentes: se omite la ocurrencia histórica")
est = intentar(obtener_capa, "estaciones_bomberos", mensaje="Sin estaciones: se omite el tiempo de respuesta")
hid = intentar(obtener_capa, "hidrantes", mensaje="Sin hidrantes: se omite la distancia al hidrante")
sens = None
if edif is not None:
unidades = process.unidades_analisis()
var = urbano.variables_unidad(edif, unidades, inc, est, hid)
pesos = parametros()["incendio_urbano"]["pesos"]
base = indices.incendio_urbano(var)
sens = indices.sensibilidad_pesos(var, pesos)
sens.insert(0, "id_unidad", var["id_unidad"])
sens["indice_base"] = base
sens["ancho_rango"] = sens["rango_p95"] - sens["rango_p05"]
display(sens.sort_values("indice_base", ascending=False).head(10).round(2))WARNING sidro.fetch: manzanas_censo: falló nivel nacional/usuario -> Archivo de usuario no encontrado: /Users/mauricio/Documents/Data-science-local/SIDRo/data/user/dane_mgn_manzanas_cnpv2018.gpkg
WARNING sidro.process: Unidades: manzanas_censo no disponible (No se pudo obtener 'manzanas_censo'. Intentos: [{'nivel': 'nacional', 'tipo': 'usuario', 'error': 'Archivo de usuario no encontrado: /Users/mauricio/Documents/Data-science-local/SIDRo/data/user/dane_mgn_manzanas_cnpv2018.gpkg'}])
rango_p05 y rango_p95 delimitan el intervalo en que cae el puesto de cada unidad en el 90 % de las
simulaciones (1 = la más alta). Un intervalo ancho indica que el puesto depende mucho de los pesos.
if sens is not None:
top = sens.sort_values("indice_base", ascending=False).head(15)
fig, ax = plt.subplots(figsize=(7, 4))
y = np.arange(len(top))
ax.hlines(y, top.rango_p05, top.rango_p95, color="#bc6c25")
ax.plot(top.rango_mediano, y, "o", color="#8c2d04")
ax.set_yticks(y, top.id_unidad), ax.invert_yaxis(), ax.invert_xaxis()
ax.set_xlabel("Puesto en el ranking (1 = más alto), mediana e intervalo del 90 %")
ax.grid(alpha=0.3)
fig
Probabilidad de estar entre las más altas¶
if sens is not None:
k = max(1, round(0.2 * len(var)))
prob = urbano.probabilidad_top_k(var, pesos, k)
sens["prob_top"] = prob.values
resumen = sens.sort_values("prob_top", ascending=False).head(10)[["id_unidad", "indice_base", "prob_top"]]
print(f"Fracción de simulaciones en que la unidad queda entre el 20 % más alto ({k} unidades):")
display(resumen.round(2))
robustas = int((sens.prob_top >= 0.9).sum())
print(f"{robustas} unidades están entre las más altas en al menos 90 % de las simulaciones")Fracción de simulaciones en que la unidad queda entre el 20 % más alto (11 unidades):
5 unidades están entre las más altas en al menos 90 % de las simulaciones
Las unidades con probabilidad cercana a 1 son robustas: salen entre las más altas con casi cualquier juicio razonable de pesos, y son las candidatas más sólidas para priorizar. Las de probabilidad intermedia dependen de la ponderación y requieren una decisión explícita.
Guardar el resumen¶
if sens is not None:
from sidro import export
export.guardar_resumen("incendio_urbano_sensibilidad",
{"pesos_base": pesos, "unidades": sens.drop(columns="id_unidad").assign(
id_unidad=sens["id_unidad"]).to_dict("records")})