Dataset espacial del envejecimiento demográfico en los municipios de Italia

Elaboración propia a partir de datos oficiales de población residente y cartografía administrativa de ISTAT (2025)

demografía
italia
istat
análisis espacial
Autor/a
Afiliación

Giulio Aiello

Universitat de València

Fecha de publicación

1 de abril de 2026

Input

Se ha utilizado un conjunto de datos procedente del Instituto Nacional de Estadística (ISTAT), que proporciona información detallada sobre la población residente en Italia a nivel municipal para el año 2025.

Este conjunto de datos presenta un alto nivel de desagregación por edad, lo que permite la construcción de indicadores demográficos relevantes para el análisis territorial.

Con el objetivo de incorporar la dimensión espacial, se ha integrado un shapefile oficial de los límites administrativos de los municipios italianos (ISTAT, 2025), lo que permite georreferenciar la información y realizar análisis espaciales.

El propósito de este trabajo es transformar el conjunto de datos original en un dataset estructurado, georreferenciado y analíticamente más útil, mediante la agregación de variables y la construcción de indicadores demográficos a escala municipal.

Las fuentes oficiales utilizadas están disponibles en los siguientes enlaces:

Este enfoque permite no solo mejorar la calidad del dato original, sino también facilitar su reutilización en análisis espaciales y estudios demográficos comparativos.

# Librerías
library(sf)
library(dplyr)
library(readr)
library(ggplot2)
library(here)

# Lectura del dataset de población
pop_raw <- read_delim(
  here("data/2526020001/popolazione_istat_2025.csv"),
  delim = ";",
  skip = 1,
  show_col_types = FALSE
)

# Lectura del shapefile de municipios
comuni <- st_read(
  here("data/2526020001/confini_istat_2025", "Com01012025_g", "Com01012025_g_WGS84.shp"),
  quiet = TRUE
)

Descripción

El conjunto de datos original presenta un elevado nivel de desagregación, ya que incluye información detallada por edad para cada municipio. Esta característica, aunque rica en contenido, dificulta su utilización directa en análisis territoriales, siendo necesario un proceso de agregación que permita sintetizar la información en indicadores demográficos interpretables.

Además, el dataset demográfico no contiene información geométrica, lo que impide su representación espacial y limita su uso en el ámbito de los datos espaciales.

Por otro lado, el shapefile de municipios proporciona la geometría necesaria para el análisis espacial, pero carece de información demográfica. Por tanto, resulta imprescindible combinar ambos conjuntos de datos mediante un identificador común que permita integrar la dimensión espacial y la información estadística.

Este proceso de integración y transformación constituye un paso fundamental para la construcción de un dataset georreferenciado, adecuado para el análisis territorial y la aplicación de técnicas de análisis espacial.

# Exploración inicial
glimpse(pop_raw)
Rows: 805,392
Columns: 20
$ `Codice comune`                                          <chr> "028001", "02…
$ Comune                                                   <chr> "Abano Terme"…
$ Età                                                      <dbl> 0, 1, 2, 3, 4…
$ Celibi                                                   <dbl> 57, 59, 66, 7…
$ Coniugati                                                <dbl> 0, 0, 0, 0, 0…
$ Divorziati                                               <dbl> 0, 0, 0, 0, 0…
$ Vedovi                                                   <dbl> 0, 0, 0, 0, 0…
$ `Uniti civilmente`                                       <dbl> 0, 0, 0, 0, 0…
$ `Maschi già in unione civile (per scioglimento unione)`  <dbl> 0, 0, 0, 0, 0…
$ `Maschi già in unione civile (per decesso del partner)`  <dbl> 0, 0, 0, 0, 0…
$ `Totale maschi`                                          <dbl> 57, 59, 66, 7…
$ Nubili                                                   <dbl> 48, 51, 44, 6…
$ Coniugate                                                <dbl> 0, 0, 0, 0, 0…
$ Divorziate                                               <dbl> 0, 0, 0, 0, 0…
$ Vedove                                                   <dbl> 0, 0, 0, 0, 0…
$ `Unite civilmente`                                       <dbl> 0, 0, 0, 0, 0…
$ `Femmine già in unione civile (per scioglimento unione)` <dbl> 0, 0, 0, 0, 0…
$ `Femmine già in unione civile (per decesso del partner)` <dbl> 0, 0, 0, 0, 0…
$ `Totale femmine`                                         <dbl> 48, 51, 44, 6…
$ Totale                                                   <dbl> 105, 110, 110…
glimpse(comuni)
Rows: 7,896
Columns: 13
$ COD_RIP    <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ COD_REG    <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ COD_PROV   <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ COD_CM     <dbl> 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,…
$ COD_UTS    <dbl> 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,…
$ PRO_COM    <dbl> 1001, 1002, 1003, 1004, 1006, 1007, 1008, 1009, 1010, 1011,…
$ PRO_COM_T  <chr> "001001", "001002", "001003", "001004", "001006", "001007",…
$ COMUNE     <chr> "Agliè", "Airasca", "Ala di Stura", "Albiano d'Ivrea", "Alm…
$ COMUNE_A   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ CC_UTS     <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ Shape_Leng <dbl> 15843.982, 16188.945, 29257.735, 16429.908, 16104.285, 8894…
$ Shape_Area <dbl> 13240682, 16032725, 46174949, 11677019, 17987914, 5555692, …
$ geometry   <MULTIPOLYGON [m]> MULTIPOLYGON (((405359.6 50..., MULTIPOLYGON (…
names(pop_raw)
 [1] "Codice comune"                                         
 [2] "Comune"                                                
 [3] "Età"                                                   
 [4] "Celibi"                                                
 [5] "Coniugati"                                             
 [6] "Divorziati"                                            
 [7] "Vedovi"                                                
 [8] "Uniti civilmente"                                      
 [9] "Maschi già in unione civile (per scioglimento unione)" 
[10] "Maschi già in unione civile (per decesso del partner)" 
[11] "Totale maschi"                                         
[12] "Nubili"                                                
[13] "Coniugate"                                             
[14] "Divorziate"                                            
[15] "Vedove"                                                
[16] "Unite civilmente"                                      
[17] "Femmine già in unione civile (per scioglimento unione)"
[18] "Femmine già in unione civile (per decesso del partner)"
[19] "Totale femmine"                                        
[20] "Totale"                                                
names(comuni)
 [1] "COD_RIP"    "COD_REG"    "COD_PROV"   "COD_CM"     "COD_UTS"   
 [6] "PRO_COM"    "PRO_COM_T"  "COMUNE"     "COMUNE_A"   "CC_UTS"    
[11] "Shape_Leng" "Shape_Area" "geometry"  
dim(pop_raw)
[1] 805392     20
dim(comuni)
[1] 7896   13

Los resultados de la exploración inicial permiten identificar las principales características de los datos utilizados.

El dataset pop_raw presenta un elevado nivel de desagregación, con más de 800.000 observaciones, donde cada fila corresponde a una combinación específica de municipio, edad y condición demográfica. Esta estructura confirma que se trata de un dataset de tipo micro-agregado, no directamente utilizable para análisis territoriales sin un proceso previo de agregación.

Por otro lado, el dataset comuni contiene la información geográfica de los municipios italianos, con aproximadamente 7.900 unidades espaciales y su correspondiente geometría. Este dataset constituye la base espacial necesaria para la representación cartográfica.

El análisis de los nombres de variables y dimensiones permite verificar la coherencia entre ambos datasets, identificando la variable clave de unión (codice_comune), lo que hace posible integrar la información demográfica con la dimensión espacial.

En conjunto, esta exploración inicial confirma la necesidad de realizar un proceso de agregación y posterior integración espacial para construir un dataset adecuado para el análisis territorial del envejecimiento demográfico.

Tratamiento

Se ha llevado a cabo un proceso de transformación del dataset original con el objetivo de obtener un conjunto de datos coherente, estructurado y adecuado para el análisis territorial.

En una primera fase, se ha realizado la limpieza y preparación del dataset demográfico, incluyendo la selección y renombrado de variables relevantes, así como la conversión de tipos de datos para garantizar su consistencia. Además, se ha estandarizado el identificador municipal con el fin de asegurar la correcta integración posterior con la información espacial.

Posteriormente, se ha llevado a cabo una agregación de los datos a nivel municipal, calculando la población total y distintos grupos de edad (0–14, 15–64 y 65+). A partir de estos valores, se han construido indicadores demográficos clave, como la proporción de población joven, la proporción de población envejecida y el índice de envejecimiento.

En una segunda fase, se ha preparado el shapefile de municipios, asegurando la coherencia del identificador geográfico y su compatibilidad con el dataset demográfico.

Finalmente, ambos conjuntos de datos se han integrado mediante una operación de unión espacial basada en el código municipal, obteniendo un dataset georreferenciado completo. Se ha realizado un control de calidad final para verificar la correcta integración de los datos y la ausencia de valores faltantes en las variables principales.

# --- LIMPIEZA Y PREPARACIÓN DEL DATASET ---

pop_comuni <- pop_raw %>%
  rename(
    codice_comune = `Codice comune`,
    comune = Comune,
    eta = `Età`,
    totale = Totale
  ) %>%
  mutate(
    codice_comune = sprintf("%06d", as.integer(codice_comune)),
    eta = as.integer(eta),
    totale = as.numeric(totale)
  ) %>%
  group_by(codice_comune, comune) %>%
  summarise(
    popolazione_totale = sum(totale, na.rm = TRUE),
    popolazione_0_14 = sum(totale[eta >= 0 & eta <= 14], na.rm = TRUE),
    popolazione_15_64 = sum(totale[eta >= 15 & eta <= 64], na.rm = TRUE),
    popolazione_65_plus = sum(totale[eta >= 65], na.rm = TRUE),
    .groups = "drop"
  ) %>%
  mutate(
    quota_giovani = popolazione_0_14 / popolazione_totale * 100,
    quota_anziani = popolazione_65_plus / popolazione_totale * 100,
    indice_vecchiaia = ifelse(
      popolazione_0_14 > 0,
      popolazione_65_plus / popolazione_0_14 * 100,
      NA_real_
    )
  )
pop_comuni
# A tibble: 7,896 × 9
   codice_comune comune    popolazione_totale popolazione_0_14 popolazione_15_64
   <chr>         <chr>                  <dbl>            <dbl>             <dbl>
 1 001001        Agliè                   5170              290              1579
 2 001002        Airasca                 7390              453              2328
 3 001003        Ala di S…                926               48               298
 4 001004        Albiano …               3248              170               992
 5 001006        Almese                 12594              697              3917
 6 001007        Alpette                  496               17               144
 7 001008        Alpignano              32988             1704              9955
 8 001009        Andezeno                3990              255              1229
 9 001010        Andrate                  932               44               288
10 001011        Angrogna                1608               76               516
# ℹ 7,886 more rows
# ℹ 4 more variables: popolazione_65_plus <dbl>, quota_giovani <dbl>,
#   quota_anziani <dbl>, indice_vecchiaia <dbl>

Los resultados obtenidos muestran un dataset agregado a nivel municipal, en el que cada fila representa un municipio con su población total, su distribución por grupos de edad y una serie de indicadores demográficos sintéticos.

Se observa que la estructura del dataset es coherente con el objetivo del análisis, ya que incluye variables clave como la población de 65 y más años, la proporción de población joven, la proporción de población envejecida y el índice de envejecimiento.

Este proceso de agregación resulta fundamental para transformar un conjunto de datos altamente desagregado en una base de datos interpretable desde una perspectiva territorial y adecuada para posteriores análisis espaciales.

# --- PREPARACIÓN DEL SHAPEFILE ---

comuni2 <- comuni %>%
  mutate(
    codice_comune = sprintf("%06d", as.integer(PRO_COM))
  )
comuni2
Simple feature collection with 7896 features and 13 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 313279.3 ymin: 3933777 xmax: 1312016 ymax: 5220268
Projected CRS: WGS 84 / UTM zone 32N
First 10 features:
   COD_RIP COD_REG COD_PROV COD_CM COD_UTS PRO_COM PRO_COM_T          COMUNE
1        1       1        1    201     201    1001    001001           Agliè
2        1       1        1    201     201    1002    001002         Airasca
3        1       1        1    201     201    1003    001003    Ala di Stura
4        1       1        1    201     201    1004    001004 Albiano d'Ivrea
5        1       1        1    201     201    1006    001006          Almese
6        1       1        1    201     201    1007    001007         Alpette
7        1       1        1    201     201    1008    001008       Alpignano
8        1       1        1    201     201    1009    001009        Andezeno
9        1       1        1    201     201    1010    001010         Andrate
10       1       1        1    201     201    1011    001011        Angrogna
   COMUNE_A CC_UTS Shape_Leng Shape_Area                       geometry
1      <NA>      0  15843.982   13240682 MULTIPOLYGON (((405359.6 50...
2      <NA>      0  16188.945   16032725 MULTIPOLYGON (((381550 4977...
3      <NA>      0  29257.735   46174949 MULTIPOLYGON (((365491.7 50...
4      <NA>      0  16429.908   11677019 MULTIPOLYGON (((416079.3 50...
5      <NA>      0  16104.285   17987914 MULTIPOLYGON (((377846.7 49...
6      <NA>      0   8894.833    5555692 MULTIPOLYGON (((388946 5030...
7      <NA>      0  15190.540   11897218 MULTIPOLYGON (((383151.2 49...
8      <NA>      0  11473.220    7476554 MULTIPOLYGON (((410375.6 49...
9      <NA>      0  18677.517    9357340 MULTIPOLYGON (((413783.4 50...
10     <NA>      0  31461.845   38408771 MULTIPOLYGON (((353816.5 49...
   codice_comune
1         001001
2         001002
3         001003
4         001004
5         001006
6         001007
7         001008
8         001009
9         001010
10        001011

El shapefile presenta correctamente la geometría de los municipios italianos, con un total de 7896 unidades espaciales y un sistema de referencia WGS84.

La creación del identificador codice_comune garantiza la compatibilidad con el dataset demográfico, permitiendo una integración precisa entre información espacial y atributos estadísticos.

Este paso es clave para asegurar la correcta alineación entre ambas fuentes de datos.

# --- UNIÓN DE DATOS ---

dataset_finale <- comuni2 %>%
  left_join(pop_comuni, by = "codice_comune")
dataset_finale
Simple feature collection with 7896 features and 21 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 313279.3 ymin: 3933777 xmax: 1312016 ymax: 5220268
Projected CRS: WGS 84 / UTM zone 32N
First 10 features:
   COD_RIP COD_REG COD_PROV COD_CM COD_UTS PRO_COM PRO_COM_T          COMUNE
1        1       1        1    201     201    1001    001001           Agliè
2        1       1        1    201     201    1002    001002         Airasca
3        1       1        1    201     201    1003    001003    Ala di Stura
4        1       1        1    201     201    1004    001004 Albiano d'Ivrea
5        1       1        1    201     201    1006    001006          Almese
6        1       1        1    201     201    1007    001007         Alpette
7        1       1        1    201     201    1008    001008       Alpignano
8        1       1        1    201     201    1009    001009        Andezeno
9        1       1        1    201     201    1010    001010         Andrate
10       1       1        1    201     201    1011    001011        Angrogna
   COMUNE_A CC_UTS Shape_Leng Shape_Area codice_comune          comune
1      <NA>      0  15843.982   13240682        001001           Agliè
2      <NA>      0  16188.945   16032725        001002         Airasca
3      <NA>      0  29257.735   46174949        001003    Ala di Stura
4      <NA>      0  16429.908   11677019        001004 Albiano d'Ivrea
5      <NA>      0  16104.285   17987914        001006          Almese
6      <NA>      0   8894.833    5555692        001007         Alpette
7      <NA>      0  15190.540   11897218        001008       Alpignano
8      <NA>      0  11473.220    7476554        001009        Andezeno
9      <NA>      0  18677.517    9357340        001010         Andrate
10     <NA>      0  31461.845   38408771        001011        Angrogna
   popolazione_totale popolazione_0_14 popolazione_15_64 popolazione_65_plus
1                5170              290              1579                3301
2                7390              453              2328                4609
3                 926               48               298                 580
4                3248              170               992                2086
5               12594              697              3917                7980
6                 496               17               144                 335
7               32988             1704              9955               21329
8                3990              255              1229                2506
9                 932               44               288                 600
10               1608               76               516                1016
   quota_giovani quota_anziani indice_vecchiaia                       geometry
1       5.609284      63.84913        1138.2759 MULTIPOLYGON (((405359.6 50...
2       6.129905      62.36806        1017.4393 MULTIPOLYGON (((381550 4977...
3       5.183585      62.63499        1208.3333 MULTIPOLYGON (((365491.7 50...
4       5.233990      64.22414        1227.0588 MULTIPOLYGON (((416079.3 50...
5       5.534381      63.36351        1144.9067 MULTIPOLYGON (((377846.7 49...
6       3.427419      67.54032        1970.5882 MULTIPOLYGON (((388946 5030...
7       5.165515      64.65684        1251.7019 MULTIPOLYGON (((383151.2 49...
8       6.390977      62.80702         982.7451 MULTIPOLYGON (((410375.6 49...
9       4.721030      64.37768        1363.6364 MULTIPOLYGON (((413783.4 50...
10      4.726368      63.18408        1336.8421 MULTIPOLYGON (((353816.5 49...

El resultado de la unión muestra un dataset georreferenciado completo, donde cada municipio incorpora tanto su geometría como la información demográfica correspondiente.

Se observa que las variables han sido correctamente integradas, incluyendo la población total, los grupos de edad y los indicadores derivados como la cuota de jóvenes, la cuota de población envejecida y el índice de envejecimiento.

Este dataset constituye la base para el posterior análisis espacial, al combinar información estadística y geográfica en una única estructura.

# --- CONTROL DE CALIDAD ---

sum(is.na(dataset_finale$popolazione_totale))
[1] 0
nrow(dataset_finale)
[1] 7896

El control de calidad confirma que no existen valores faltantes en la variable de población total y que el número de observaciones coincide con el total de municipios (7896).

Esto indica que la integración de los datos se ha realizado correctamente y que el dataset final es completo y consistente, garantizando su fiabilidad para el análisis espacial posterior.

Análisis exploratorio

Representación cartográfica del índice de envejecimiento

library(classInt)
# Selección de variables finales
dataset_export <- dataset_finale %>%
  select(
    codice_comune,
    nome_comune = COMUNE,
    popolazione_totale,
    popolazione_0_14,
    popolazione_15_64,
    popolazione_65_plus,
    quota_giovani,
    quota_anziani,
    indice_vecchiaia,
    geometry
  )

# Clasificación del índice de envejecimiento en quintiles
breaks_iv <- classIntervals(dataset_export$indice_vecchiaia, n = 5, style = "quantile")

dataset_mapa <- dataset_export %>%
  mutate(
    clase_indice = cut(
      indice_vecchiaia,
      breaks = breaks_iv$brks,
      include.lowest = TRUE,
      labels = c("Muy bajo", "Bajo", "Medio", "Alto", "Muy alto"),
      dig.lab = 10
    )
  )

mapa_indice<-ggplot(dataset_mapa) +
  geom_sf(aes(fill = clase_indice), color = NA) +
  scale_fill_brewer(
    palette = "YlOrRd",
    na.value = "grey90",
    name = "Nivel de envejecimiento"
  ) +
  labs(
    title = "Patrón territorial del envejecimiento demográfico en Italia",
    subtitle = "Clasificación en quintiles del índice de envejecimiento municipal (2025)",
    caption = "Fuente: ISTAT. Elaboración propia."
  ) +
  theme_minimal() +
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    axis.title = element_blank(),
    plot.title = element_text(size = 14, face = "bold"),
    plot.subtitle = element_text(size = 11),
    legend.title = element_text(size = 10),
    legend.text = element_text(size = 9)
  )
mapa_indice

La cartografía evidencia una marcada diferenciación territorial en la estructura demográfica de Italia. Los niveles más altos de envejecimiento se concentran en numerosos municipios del interior y en amplias áreas del centro y norte del país, mientras que otras zonas presentan una estructura relativamente más joven.

Este patrón espacial refleja un proceso de envejecimiento demográfico territorialmente desigual, lo que pone de relieve la importancia de analizar estos fenómenos a escala municipal.

Autocorrelación espacial: índice global de Moran y Moran scatterplot

# Librerías para análisis espacial
library(spdep)
library(sf)
library(dplyr)

# Selección de municipios con índice de envejecimiento disponible
dataset_moran <- dataset_mapa %>%
  filter(!is.na(indice_vecchiaia))

# Crear vecinos espaciales (contigüidad tipo queen)
vecinos <- poly2nb(dataset_moran)

# Convertir a lista de pesos espaciales
pesos <- nb2listw(vecinos, style = "W", zero.policy = TRUE)

# Calcular Moran's I
moran_test <- moran.test(
  dataset_moran$indice_vecchiaia,
  pesos,
  zero.policy = TRUE
)

moran_test

    Moran I test under randomisation

data:  dataset_moran$indice_vecchiaia  
weights: pesos  
n reduced by no-neighbour observations  

Moran I statistic standard deviate = 46.168, p-value < 2.2e-16
alternative hypothesis: greater
sample estimates:
Moran I statistic       Expectation          Variance 
     3.080882e-01     -1.269519e-04      4.456898e-05 
sum(is.na(dataset_mapa$indice_vecchiaia))
[1] 4

El resultado del índice de Moran muestra un valor positivo y estadísticamente significativo (I ≈ 0.308; p-value < 2.2e-16), lo que indica la existencia de una clara autocorrelación espacial en el envejecimiento demográfico en Italia.

Este valor positivo implica que los municipios con niveles elevados de envejecimiento tienden a situarse próximos entre sí, formando agrupaciones territoriales, mientras que los municipios con estructuras demográficas más jóvenes también tienden a concentrarse espacialmente.

La significatividad estadística del resultado permite rechazar la hipótesis nula de aleatoriedad espacial, confirmando que el patrón observado no es fruto del azar, sino que responde a dinámicas territoriales bien definidas.

En coherencia con la representación cartográfica, este resultado evidencia una estructura espacial marcada, caracterizada por la concentración de municipios envejecidos en zonas del interior y del norte del país, frente a áreas con menor envejecimiento en otras regiones.

En conjunto, el análisis confirma que el envejecimiento demográfico en Italia presenta una fuerte dependencia espacial, lo que pone de relieve la importancia de incorporar herramientas de análisis espacial en el estudio de fenómenos demográficos a escala municipal.

# Moran scatterplot en ggplot (versión final)
library(ggplot2)
library(dplyr)
library(spdep)

# Cálculo del lag espacial
dataset_moran_plot <- dataset_moran %>%
  mutate(
    lag_indice = lag.listw(pesos, indice_vecchiaia, zero.policy = TRUE)
  )

moran_scatter<-ggplot(dataset_moran_plot, aes(x = indice_vecchiaia, y = lag_indice)) +
  geom_point(alpha = 0.35, size = 1.2, color = "#1f4e79") +
  geom_smooth(method = "lm", se = FALSE, color = "#222222", linewidth = 0.9) +
  geom_vline(
    xintercept = mean(dataset_moran_plot$indice_vecchiaia, na.rm = TRUE),
    linetype = "dashed", color = "#b22222", linewidth = 0.7
  ) +
  geom_hline(
    yintercept = mean(dataset_moran_plot$lag_indice, na.rm = TRUE),
    linetype = "dashed", color = "#b22222", linewidth = 0.7
  ) +
  labs(
    title = "Moran scatterplot del envejecimiento demográfico en Italia",
    subtitle = "Relación entre el índice de envejecimiento municipal y la media espacial de los municipios vecinos",
    x = "Índice de envejecimiento",
    y = "Media espacial de los vecinos",
    caption = "Fuente: ISTAT. Elaboración propia."
  ) +
  theme_minimal(base_size = 12) +
  theme(
    panel.grid.minor = element_blank(),
    plot.title = element_text(face = "bold", size = 15),
    plot.subtitle = element_text(size = 11),
    axis.title = element_text(size = 11),
    axis.text = element_text(size = 10),
    plot.caption = element_text(size = 9)
  )
moran_scatter
`geom_smooth()` using formula = 'y ~ x'

El Moran scatterplot permite analizar la relación entre el índice de envejecimiento de cada municipio y la media espacial de los municipios vecinos.

La pendiente positiva de la recta de regresión evidencia una autocorrelación espacial positiva, en coherencia con el valor del índice de Moran previamente estimado. Esto indica que los municipios con altos niveles de envejecimiento tienden a situarse próximos a otros municipios también envejecidos, mientras que los municipios con valores bajos se agrupan entre sí.

Las líneas de referencia, que representan las medias globales, permiten identificar los cuadrantes del gráfico y facilitan la interpretación de los patrones espaciales. En particular, se observa una clara concentración de observaciones en los cuadrantes alto-alto y bajo-bajo, lo que confirma la existencia de clusters territoriales bien definidos.

Asimismo, la dispersión relativamente limitada en torno a la recta de ajuste refuerza la consistencia del patrón espacial observado, indicando que el envejecimiento demográfico no responde a una distribución aleatoria, sino a dinámicas territoriales estructuradas.

En conjunto, este resultado confirma que el envejecimiento en Italia presenta una fuerte dependencia espacial, lo que subraya la importancia de incorporar herramientas de análisis espacial en el estudio de fenómenos demográficos a escala municipal.

Análisis local de autocorrelación espacial (LISA)

Con el objetivo de profundizar en la estructura espacial del envejecimiento demográfico, se aplica el análisis local de autocorrelación espacial (LISA).

A diferencia del índice global de Moran, este enfoque permite identificar patrones espaciales a nivel local, distinguiendo entre agrupaciones de municipios con valores similares (clusters) y posibles valores atípicos.

En particular, se clasifican los municipios en función de la relación entre su nivel de envejecimiento y el de sus vecinos, permitiendo detectar áreas con concentración de envejecimiento elevado o bajo.

library(spdep)

# Local Moran (LISA)
lisa <- localmoran(dataset_moran$indice_vecchiaia, pesos, zero.policy = TRUE)

dataset_moran$lisa_I <- lisa[,1]
dataset_moran$lisa_p <- lisa[,5]

# Clasificación de clusters
dataset_moran <- dataset_moran %>%
  mutate(
    lag_indice = lag.listw(pesos, indice_vecchiaia, zero.policy = TRUE),
    cluster = case_when(
      indice_vecchiaia > mean(indice_vecchiaia, na.rm = TRUE) &
      lag_indice > mean(lag_indice, na.rm = TRUE) ~ "High-High",

      indice_vecchiaia < mean(indice_vecchiaia, na.rm = TRUE) &
      lag_indice < mean(lag_indice, na.rm = TRUE) ~ "Low-Low",

      indice_vecchiaia > mean(indice_vecchiaia, na.rm = TRUE) &
      lag_indice < mean(lag_indice, na.rm = TRUE) ~ "High-Low",

      indice_vecchiaia < mean(indice_vecchiaia, na.rm = TRUE) &
      lag_indice > mean(lag_indice, na.rm = TRUE) ~ "Low-High",

      TRUE ~ "No significativo"
    )
  )
mapa_lisa<-ggplot(dataset_moran) +
  geom_sf(aes(fill = cluster), color = NA) +
  scale_fill_manual(
    values = c(
      "High-High" = "#b2182b",
      "Low-Low" = "#2166ac",
      "High-Low" = "#ef8a62",
      "Low-High" = "#67a9cf",
      "No significativo" = "grey85"
    )
  ) +
  labs(
    title = "Clusters locales de envejecimiento (LISA)",
    subtitle = "Identificación de patrones espaciales locales",
    fill = "Tipo de cluster",
    caption = "Fuente: ISTAT. Elaboración propia."
  ) +
  theme_minimal()
mapa_lisa

El mapa LISA permite identificar la distribución espacial de clusters locales de envejecimiento en Italia, proporcionando una visión más detallada respecto al análisis global.

Se observan clusters High-High (alto envejecimiento rodeado de municipios similares) principalmente en zonas del interior y del norte del país, lo que indica áreas donde el envejecimiento demográfico se concentra territorialmente.

Por otro lado, los clusters Low-Low (bajo envejecimiento rodeado de municipios jóvenes) se localizan en determinadas áreas, reflejando estructuras demográficas más dinámicas.

Asimismo, la presencia de clusters High-Low y Low-High evidencia la existencia de municipios atípicos, es decir, territorios cuyo comportamiento demográfico difiere del de su entorno inmediato.

En conjunto, estos resultados confirman que el envejecimiento demográfico en Italia presenta una estructura espacial compleja, caracterizada por patrones locales bien definidos, reforzando la importancia del análisis espacial para comprender las dinámicas territoriales.

Output

Como resultado del proceso descrito, se ha obtenido un dataset espacial a nivel municipal que integra información demográfica y geográfica para toda Italia.

El conjunto de datos final contiene variables seleccionadas sobre población total, estructura por edad e indicadores demográficos sintéticos, como la proporción de población joven, la proporción de población envejecida y el índice de envejecimiento.

Además, el dataset generado ha permitido desarrollar diferentes productos analíticos y cartográficos, incluyendo la representación territorial del índice de envejecimiento, el Moran scatterplot y el mapa de clusters locales LISA.

El fichero final se ha exportado en formato GeoPackage, manteniendo la geometría municipal y permitiendo su reutilización en futuros análisis espaciales. El sistema de referencia utilizado es WGS84 / UTM zone 32N.

A continuación, se ponen a disposición tanto el dataset final como los principales productos gráficos generados en este trabajo.

# Guardado del dataset final
st_write(
  dataset_export,
  here("dataset_poblacion_italia_2025.gpkg"),
  delete_dsn = TRUE
)
Deleting source `C:/Users/scorp/Dropbox/01 PROFESOR/06 Innovación Educativa/DataEnhanceUV/dataset_poblacion_italia_2025.gpkg' using driver `GPKG'
Writing layer `dataset_poblacion_italia_2025' to data source 
  `C:/Users/scorp/Dropbox/01 PROFESOR/06 Innovación Educativa/DataEnhanceUV/dataset_poblacion_italia_2025.gpkg' using driver `GPKG'
Writing 7896 features with 9 fields and geometry type Multi Polygon.

La exportación confirma que el dataset final contiene 7896 municipios y 9 variables atributivas, además de la geometría multipoligonal correspondiente.

Visualización interactiva del envejecimiento demográfico

Con el fin de facilitar la exploración interactiva del dataset sin comprometer la legibilidad ni el rendimiento de la visualización, se ha construido una versión simplificada del mapa utilizando los 110 municipios más poblados de Italia.

La visualización combina los límites municipales con puntos interactivos situados en los centroides de cada municipio, lo que permite consultar información demográfica clave y explorar tanto el índice de envejecimiento como los clusters LISA.

library(leaflet)
library(htmltools)
library(sf)
library(dplyr)

# 1. Preparación de los datos
dataset_export_leaflet <- dataset_export %>%
  st_make_valid() %>%
  st_transform(4326)

dataset_lisa_leaflet <- dataset_moran %>%
  st_make_valid() %>%
  st_transform(4326) %>%
  st_drop_geometry() %>%
  select(codice_comune, cluster)

dataset_leaflet <- dataset_export_leaflet %>%
  left_join(dataset_lisa_leaflet, by = "codice_comune")

# 2. Selección de los 110 municipios más poblados
dataset_interactivo <- dataset_leaflet %>%
  arrange(desc(popolazione_totale)) %>%
  slice_head(n = 110)

# 3. Centroides para los puntos interactivos
centroides <- st_centroid(dataset_interactivo)

# 4. Paletas
pal_indice <- colorNumeric(
  palette = "YlOrRd",
  domain = dataset_interactivo$indice_vecchiaia,
  na.color = "#d9d9d9"
)

pal_lisa <- colorFactor(
  palette = c(
    "High-High" = "#b2182b",
    "Low-Low" = "#2166ac",
    "High-Low" = "#ef8a62",
    "Low-High" = "#67a9cf",
    "No significativo" = "#cccccc"
  ),
  domain = dataset_interactivo$cluster
)

# 5. Popup
popup_text <- paste0(
  "<strong>Municipio:</strong> ", dataset_interactivo$nome_comune, "<br/>",
  "<strong>Población total:</strong> ", format(dataset_interactivo$popolazione_totale, big.mark = ".", decimal.mark = ","), "<br/>",
  "<strong>Población 65+:</strong> ", format(dataset_interactivo$popolazione_65_plus, big.mark = ".", decimal.mark = ","), "<br/>",
  "<strong>Cuota de población envejecida (%):</strong> ", round(dataset_interactivo$quota_anziani, 2), "<br/>",
  "<strong>Índice de envejecimiento:</strong> ", round(dataset_interactivo$indice_vecchiaia, 2), "<br/>",
  "<strong>Cluster LISA:</strong> ", ifelse(is.na(dataset_interactivo$cluster), "No disponible", dataset_interactivo$cluster)
)

# 6. Mapa interactivo
mapa_interactivo<-leaflet() |>
  addProviderTiles(providers$CartoDB.Positron) |>
  
  # Contornos municipales
  addPolygons(
    data = dataset_interactivo,
    fill = FALSE,
    color = "#555555",
    weight = 1,
    opacity = 0.8,
    group = "Límites municipales"
  ) |>
  
  # Puntos por índice de envejecimiento
  addCircleMarkers(
    data = centroides,
    radius = 6,
    stroke = TRUE,
    weight = 1,
    color = "#333333",
    fillColor = ~pal_indice(indice_vecchiaia),
    fillOpacity = 0.9,
    popup = lapply(popup_text, HTML),
    group = "Índice de envejecimiento"
  ) |>
  
  # Puntos por cluster LISA
  addCircleMarkers(
    data = centroides,
    radius = 6,
    stroke = TRUE,
    weight = 1,
    color = "#333333",
    fillColor = ~pal_lisa(cluster),
    fillOpacity = 0.9,
    popup = lapply(popup_text, HTML),
    group = "Clusters LISA"
  ) |>
  
  addLayersControl(
    overlayGroups = c("Límites municipales", "Índice de envejecimiento", "Clusters LISA"),
    options = layersControlOptions(collapsed = FALSE)
  ) |>
  
  addLegend(
    pal = pal_indice,
    values = dataset_interactivo$indice_vecchiaia,
    title = "Índice de envejecimiento",
    position = "bottomright"
  ) |>
  
  hideGroup("Clusters LISA") |>
  setView(lng = 12.5, lat = 42.5, zoom = 5)
mapa_interactivo

La visualización interactiva permite explorar de manera detallada la distribución del envejecimiento demográfico en los principales municipios italianos.

A través de los puntos representados, se observa una notable heterogeneidad territorial en los niveles del índice de envejecimiento, con municipios que presentan valores significativamente elevados frente a otros con estructuras demográficas más jóvenes.

El uso de ventanas emergentes facilita el acceso a información demográfica clave, permitiendo analizar conjuntamente la población total, la proporción de población envejecida y el índice de envejecimiento para cada municipio.

Además, la posibilidad de activar la capa de clusters LISA permite identificar patrones espaciales locales, evidenciando la existencia de agrupamientos territoriales coherentes con los resultados del análisis de autocorrelación espacial.

En conjunto, esta herramienta interactiva complementa el análisis previo, aportando una dimensión aplicada que facilita la interpretación del fenómeno y la exploración del dataset generado.

Acceso a los productos finales y materiales generados

# Guardado de los productos gráficos principales
ggsave(
  filename = here("mapa_indice_envejecimiento_italia_2025.png"),
  plot = mapa_indice,
  width = 8,
  height = 6,
  dpi = 300
)

ggsave(
  filename = here("moran_scatterplot_envejecimiento_italia_2025.png"),
  plot = moran_scatter,
  width = 9,
  height = 6,
  dpi = 300
)

ggsave(
  filename = here("mapa_lisa_envejecimiento_italia_2025.png"),
  plot = mapa_lisa,
  width = 8,
  height = 6,
  dpi = 300
)

htmlwidgets::saveWidget(
  mapa_interactivo,
  file = "mapa_interactivo_envejecimiento_italia_2025.html",
  selfcontained = TRUE
)

En conjunto, tanto el dataset final como los productos cartográficos, analíticos e interactivos generados amplían significativamente las posibilidades de análisis y reutilización de la información, facilitando la exploración espacial y la toma de decisiones basadas en evidencia territorial.

Todos los outputs han sido generados siguiendo criterios de reproducibilidad, permitiendo replicar completamente el análisis a partir del código proporcionado.

El/los fichero(s) generados con este procedimiento/técnica/metodología se puede(n) descargar de aquí.



Proyecto de Innovación Educativa Emergente (PIEE-3898312)