📊 Dashboard Demográfico de Madrid
Todas las Secciones Censales | 21 Distritos | 2,450 Secciones con Datos
3,339,931
Habitantes
1,332,275
Hogares
2.51
Tamaño Medio
2,450
Secciones Visibles
🏛️ Filtrar por Distrito:
📍 Todos los Distritos (Madrid Completo)
01. Centro
02. Arganzuela
03. Retiro
04. Salamanca
05. Chamartín
06. Tetuán
07. Chamberí
08. Fuencarral-El Pardo
09. Moncloa-Aravaca
10. Latina
11. Carabanchel
12. Usera
13. Puente de Vallecas
14. Moratalaz
15. Ciudad Lineal
16. Hortaleza
17. Villaverde
18. Villa de Vallecas
19. Vicálvaro
20. San Blas-Canillejas
21. Barajas
📊 Métrica a Visualizar:
Habitantes
Total Hogares
Tamaño Medio del Hogar
Hogares de 1 Persona
Hogares de 2 Personas
Hogares de 3 Personas
Hogares de 4 Personas
Hogares de 5 o Más
Mujer Sola 16-64 años
Hombre Solo 16-64 años
Mujer Sola 65+ años
Hombre Solo 65+ años
Mujer con Menores
Hombre con Menores
Dos Adultos + 1 Menor
Dos Adultos + 2 Menores
ℹ️ Instrucciones: Selecciona un distrito para filtrar el mapa.
Elige una métrica para visualizarla con colores. Haz clic en cualquier sección para ver detalles.
| Mostrando: Madrid Completo
🎨 Leyenda del Mapa
Cargando…
📋 Secciones (0)
Cargando secciones…
🗺️ Mapa Interactivo de Madrid
Cargando mapa…
Sin datos disponibles
‘; const comp = d.composicion_hogar || {}; const h5mas = Object.entries(d.hogares_por_tamano || {}) .filter(([k]) => parseInt(k) >= 5 || k === ’15_y_mas’) .reduce((sum, [, v]) => sum + v, 0); const unipersonales = (comp.mujer_sola_16_64 || 0) + (comp.hombre_solo_16_64 || 0) + (comp.mujer_sola_65_mas || 0) + (comp.hombre_solo_65_mas || 0); const monoparentales = (comp.mujer_con_menores || 0) + (comp.hombre_con_menores || 0); let html = `Sección ${codigo}
📊 Datos Generales
👥 Por Tamaño
`;
if (Object.keys(comp).length > 0) {
html += `
🏠 Composición
`;
}
html += ‘
| Habitantes: | ${d.habitantes.toLocaleString()} |
| Hogares: | ${d.total_hogares.toLocaleString()} |
| Tamaño medio: | ${d.tamano_medio_hogar.toFixed(2)} |
| 1 pers: | ${d.hogares_por_tamano[‘1’] || 0} | 2 pers: | ${d.hogares_por_tamano[‘2’] || 0} |
| 3 pers: | ${d.hogares_por_tamano[‘3’] || 0} | 4 pers: | ${d.hogares_por_tamano[‘4’] || 0} |
| 5+ pers: | ${h5mas} | ||
| Unipersonales (${unipersonales}) | |
| Mujer 16-64: | ${comp.mujer_sola_16_64 || 0} |
| Hombre 16-64: | ${comp.hombre_solo_16_64 || 0} |
| Mujer 65+: | ${comp.mujer_sola_65_mas || 0} |
| Hombre 65+: | ${comp.hombre_solo_65_mas || 0} |
| Monoparentales (${monoparentales}) | |
| Mujer + menores: | ${comp.mujer_con_menores || 0} |
| Hombre + menores: | ${comp.hombre_con_menores || 0} |
Muy Alto (≥ ${fmt(p.p80)})
Alto (${fmt(p.p60)} – ${fmt(p.p80)})
Medio (${fmt(p.p40)} – ${fmt(p.p60)})
Bajo (${fmt(p.p20)} – ${fmt(p.p40)})
Muy Bajo (< ${fmt(p.p20)})
`;
}
// Generar lista de secciones
function generarListaSecciones() {
const lista = document.getElementById(‘section-list’);
lista.innerHTML = »;
const seccionesOrdenadas = seccionesFiltradas.sort();
const maxMostrar = 100;
const mostrar = seccionesOrdenadas.slice(0, maxMostrar);
if (seccionesOrdenadas.length > maxMostrar) {
const info = document.createElement(‘div’);
info.style.cssText = ‘padding: 10px; background: #fff3cd; border-radius: 6px; margin-bottom: 10px; font-size: 0.85em; text-align: center;’;
info.innerHTML = `Mostrando ${maxMostrar} de ${seccionesOrdenadas.length} secciones`;
lista.appendChild(info);
}
mostrar.forEach(codigo => {
const d = datosCompletos[codigo];
if (!d) return;
const valor = getValor(codigo, metricaActual);
const div = document.createElement(‘div’);
div.className = ‘section-item’;
const valorFmt = valor !== null ?
(metricaActual === ‘tamano_medio_hogar’ ? valor.toFixed(2) : valor.toLocaleString()) :
‘N/A’;
div.innerHTML = `
${codigo}
${valorFmt}
${d.habitantes.toLocaleString()} hab. | ${d.total_hogares} hogares
`;
div.onclick = function() {
sectionsLayer.eachLayer(function(layer) {
if (layer.feature.properties.codigo === codigo) {
map.fitBounds(layer.getBounds(), { padding: [50, 50] });
setTimeout(() => layer.openPopup(), 300);
}
});
};
lista.appendChild(div);
});
}
// Actualizar todo
function actualizarTodo() {
filtrarSecciones();
cargarCapa();
actualizarLeyenda();
generarListaSecciones();
}
// Resetear filtros
function resetearFiltros() {
document.getElementById(‘distrito-select’).value = ‘todos’;
document.getElementById(‘metric-select’).value = ‘habitantes’;
distritoActual = ‘todos’;
metricaActual = ‘habitantes’;
document.getElementById(‘estado-filtro’).textContent = ‘| Mostrando: Madrid Completo’;
actualizarTodo();
}
// Event listeners
document.getElementById(‘distrito-select’).addEventListener(‘change’, function(e) {
distritoActual = e.target.value;
const texto = distritoActual === ‘todos’ ?
‘Madrid Completo’ :
e.target.options[e.target.selectedIndex].text;
document.getElementById(‘estado-filtro’).textContent = ‘| Mostrando: ‘ + texto;
actualizarTodo();
});
document.getElementById(‘metric-select’).addEventListener(‘change’, function(e) {
metricaActual = e.target.value;
actualizarTodo();
});
// Inicialización
async function inicializar() {
console.log(‘Iniciando aplicación…’);
// Cargar datos
const datosOk = await cargarDatos();
if (!datosOk) return;
const geoJsonOk = await cargarGeoJSON();
if (!geoJsonOk) return;
// Inicializar mapa
map = L.map(‘map’).setView([40.4168, -3.7038], 11);
L.tileLayer(‘https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png’, {
attribution: ‘© OpenStreetMap contributors’,
maxZoom: 19
}).addTo(map);
// Primera actualización
actualizarTodo();
console.log(‘✓ Dashboard cargado completamente | Creado por David Antizar’);
}
// Ejecutar al cargar la página
window.addEventListener(‘load’, inicializar);