In [1]:
import pandas as pd
import geopandas as gpd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import os
from shapely import wkt
from jenkspy import jenks_breaks
plt.style.use('seaborn-v0_8-whitegrid')
sns.set_palette('viridis')
Energia verde e consumo di suolo¶
In [2]:
ilab_path = os.path.join(os.path.expanduser('~'),'ILAB_DATA')
work_path = os.path.join(ilab_path,'PATRIMONIO','DATA')
out_path = os.path.join(ilab_path,'PATRIMONIO','OUT')
In [3]:
resolution = 8
In [4]:
file_path = os.path.join(out_path, f"grid_{resolution:02}_adv.csv")
df = pd.read_csv(file_path)
print(f"Dataset caricato con {df.shape[0]} righe e {df.shape[1]} colonne")
Dataset caricato con 2286 righe e 336 colonne
In [5]:
# Conversione in geodataframe se possibile
if 'geometry' in df.columns:
try:
df['geometry'] = df['geometry'].apply(wkt.loads)
print("Geometria convertita correttamente")
except Exception as e:
print(f"Errore nella conversione della geometria: {e}")
Geometria convertita correttamente
In [6]:
# Controllo dei valori mancanti
missing_values = df.isnull().sum()
print("\nValori mancanti per colonna:")
missing_values[missing_values > 0]
Valori mancanti per colonna:
Out[6]:
CLC||Agricultural 1 CLC||Artificial, non-agricultural vegetated 1 CLC||Forest and semi natural 1 CLC||Industrial, commercial and transport 1 CLC||Mine, dump and construction 1 CLC||Urban 1 CLC||Water bodies 1 CLC||LABEL 1 CLC||int_a_m2 1 CLC||perc 1 ISTAT||POP_F__91 42 ISTAT||POP_M__91 42 ISTAT||POP_TOT__91 42 ISTAT||P_0_14__91 42 ISTAT||P_15_19__91 42 ISTAT||P_20_39__91 42 ISTAT||P_40_64__91 42 ISTAT||P_65_99__91 42 ISTAT||POP_F__01 41 ISTAT||POP_M__01 41 ISTAT||POP_TOT__01 41 ISTAT||P_0_14__01 41 ISTAT||P_15_19__01 41 ISTAT||P_20_39__01 41 ISTAT||P_40_64__01 41 ISTAT||P_65_99__01 41 ISTAT||POP_F__11 40 ISTAT||POP_M__11 40 ISTAT||POP_TOT__11 40 ISTAT||P_0_14__11 40 ISTAT||P_15_19__11 40 ISTAT||P_20_39__11 40 ISTAT||P_40_64__11 40 ISTAT||P_65_99__11 40 ISTAT||POP_F__21 39 ISTAT||POP_M__21 39 ISTAT||POP_TOT__21 39 ISTAT||P_0_14__21 39 ISTAT||P_15_19__21 39 ISTAT||P_20_39__21 39 ISTAT||P_40_64__21 39 ISTAT||P_65_99__21 39 ISTAT||POP_TOT__21__11 666 OMI||Compr_min 624 OMI||Compr_max 624 OMI||Loc_min 624 OMI||Loc_max 624 airbnb_airbnb||total_airbnb 1676 airbnb_airbnb||price_avg_airbnb 1682 airbnb_airbnb||beds_sum_airbnb 1676 beni_immobili_erp||total_erp 2176 beni_immobili_erp||n_abitazioni_erp 2176 beni_immobili_erp||sup_totale_erp 2176 beni_immobili_erp||sup_media_erp 2176 reddito_pro_capite||redd_cell 959 reddito_pro_capite||redd_pc 1005 dtype: int64
In [7]:
df = df.fillna(0)
In [8]:
# Verifica delle colonne relative all'uso del suolo
uso_suolo_cols = [col for col in df.columns if 'CLC||' in col]
print("\nColonne relative all'uso del suolo:")
for col in uso_suolo_cols:
print(f"{col}")
Colonne relative all'uso del suolo: CLC||Agricultural CLC||Artificial, non-agricultural vegetated CLC||Forest and semi natural CLC||Industrial, commercial and transport CLC||Mine, dump and construction CLC||Urban CLC||Water bodies CLC||LABEL CLC||int_a_m2 CLC||perc
Calcolo percentuali di uso del suolo
In [9]:
for col in [col for col in uso_suolo_cols if col not in ['CLC||LABEL', 'CLC||int_a_m2', 'CLC||perc']]:
categoria = col.replace('CLC||', '')
categoria_norm = categoria.lower().replace(' and ', '_').replace(' ', '_')
# Conversione a numerico per evitare errori
df[col] = pd.to_numeric(df[col], errors='coerce')
df['cell_a_m2'] = pd.to_numeric(df['cell_a_m2'], errors='coerce')
# Calcolo percentuale evitando divisione per zero
df[f'perc_{categoria_norm}'] = np.where(df['cell_a_m2'] > 0,
df[col] / df['cell_a_m2'] * 100,
0)
Indice di urbanizzazione¶
In [10]:
# Conversione a numerico
df['CLC||Urban'] = pd.to_numeric(df['CLC||Urban'], errors='coerce')
df['cell_a_m2'] = pd.to_numeric(df['cell_a_m2'], errors='coerce')
# Calcolo indice evitando divisione per zero
df['indice_urbanizzazione'] = np.where(df['cell_a_m2'] > 0,
df['CLC||Urban'] / df['cell_a_m2'] * 100,
0)
In [11]:
plt.figure(figsize=(10, 6))
sns.histplot(df['indice_urbanizzazione'].clip(0, 100), bins=20)
plt.title('Distribuzione dell\'indice di urbanizzazione')
plt.xlabel('Percentuale di area urbanizzata')
plt.ylabel('Numero di celle')
plt.show()
1. INDICATORE COMPOSITO: POTENZIALE PER ENERGIA VERDE¶
Componente area non urbanizzata
In [12]:
df['potenziale_base'] = 100 - df['indice_urbanizzazione']
Componente aree naturali (se disponibili)
In [13]:
if 'perc_forest_and_semi_natural' in df.columns:
df['bonus_aree_naturali'] = df['perc_forest_and_semi_natural'] * 0.2
else:
df['bonus_aree_naturali'] = 0
Componente aree agricole (se disponibili)
In [14]:
if 'perc_agricultural' in df.columns:
df['bonus_aree_agricole'] = df['perc_agricultural'] * 0.1
else:
df['bonus_aree_agricole'] = 0
Calcolo indice complessivo¶
In [15]:
df['indice_potenziale_verde'] = df['potenziale_base'] + df['bonus_aree_naturali'] + df['bonus_aree_agricole']
df['indice_potenziale_verde'] = df['indice_potenziale_verde'].clip(0, 100)
In [16]:
# Classificazione in categorie
df['classe_potenziale_verde'] = pd.cut(
df['indice_potenziale_verde'],
bins=[0, 20, 40, 60, 80, 100],
labels=['Molto basso', 'Basso', 'Medio', 'Alto', 'Molto alto']
)
In [17]:
plt.figure(figsize=(10, 6))
sns.histplot(df['indice_potenziale_verde'], bins=20)
plt.title('Distribuzione dell\'indice di potenziale per energia verde')
plt.xlabel('Indice di potenziale (0-100)')
plt.ylabel('Numero di celle')
plt.show()
In [18]:
# Distribuzione delle classi
plt.figure(figsize=(10, 6))
counts = df['classe_potenziale_verde'].value_counts().sort_index()
plt.bar(counts.index, counts.values)
plt.title('Distribuzione delle classi di potenziale per energia verde')
plt.xlabel('Classe di potenziale')
plt.ylabel('Numero di celle')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
2. INDICATORE COMPOSITO: SOSTENIBILITÀ AMBIENTALE URBANA¶
Accessibilità ai servizi
In [19]:
servizi_cittadinanza = ['infrastrutture', 'cultura', 'istruzione', 'sanita', 'sport']
access_cols = []
for col in df:
for servizio in servizi_cittadinanza:
if servizio in col:
df[col] = df[col].fillna(0)
access_cols.append(col)
In [20]:
# Calcoliamo indici di accessibilità
df['accessibilita_15min'] = df[[col for col in access_cols if '15' in col]].mean(axis=1)
df['accessibilita_30min'] = df[[col for col in access_cols if '30' in col]].mean(axis=1)
/tmp/ipykernel_1179158/1220317408.py:2: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['accessibilita_15min'] = df[[col for col in access_cols if '15' in col]].mean(axis=1) /tmp/ipykernel_1179158/1220317408.py:3: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['accessibilita_30min'] = df[[col for col in access_cols if '30' in col]].mean(axis=1)
In [21]:
# Calcoliamo un indice composito di accessibilità
df['indice_accessibilita'] = (df['accessibilita_15min'] * 2 + df['accessibilita_30min']) / 3
/tmp/ipykernel_1179158/3252611048.py:2: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['indice_accessibilita'] = (df['accessibilita_15min'] * 2 + df['accessibilita_30min']) / 3
In [22]:
# Normalizzazione dell'indice di accessibilità (0-100)
max_acc = df['indice_accessibilita'].quantile(0.95) # Uso il 95° percentile per evitare outlier
df['accessibilita_norm'] = (df['indice_accessibilita'] / max_acc * 100).clip(0, 100)
/tmp/ipykernel_1179158/3643911668.py:3: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['accessibilita_norm'] = (df['indice_accessibilita'] / max_acc * 100).clip(0, 100)
Potenziale verde
In [23]:
# Normalizzazione del potenziale verde (già calcolato)
df['verde_norm'] = df['indice_potenziale_verde']
/tmp/ipykernel_1179158/759367644.py:2: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['verde_norm'] = df['indice_potenziale_verde']
Densità abitativa
In [24]:
# Densità abitativa (se disponibile), inverso per premiare aree meno dense
df['ISTAT||POP_TOT__21'] = pd.to_numeric(df['ISTAT||POP_TOT__21'], errors='coerce').fillna(0)
df['densita_abitativa'] = np.where(df['cell_a_m2'] > 0,
df['ISTAT||POP_TOT__21'] / (df['cell_a_m2'] / 1000000),
0) # abitanti per km²
max_dens = df['densita_abitativa'].quantile(0.95) # Uso il 95° percentile per evitare outlier
df['densita_norm'] = ((max_dens - df['densita_abitativa']) / max_dens * 100).clip(0, 100)
/tmp/ipykernel_1179158/1805253285.py:3: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['densita_abitativa'] = np.where(df['cell_a_m2'] > 0, /tmp/ipykernel_1179158/1805253285.py:8: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['densita_norm'] = ((max_dens - df['densita_abitativa']) / max_dens * 100).clip(0, 100)
Calcolo dell'indice composito di sostenibilità ambientale urbana¶
In [25]:
df['indice_sostenibilita_ambientale'] = (
df['verde_norm'] * 0.5 + # 50% potenziale verde
df['accessibilita_norm'] * 0.3 + # 30% accessibilità
df['densita_norm'] * 0.2 # 20% inverso della densità
) / 100 * 100 # Normalizzazione a 0-100
/tmp/ipykernel_1179158/3432026295.py:1: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['indice_sostenibilita_ambientale'] = (
In [26]:
# Classificazione in categorie
df['classe_sostenibilita'] = pd.cut(
df['indice_sostenibilita_ambientale'],
bins=[0, 20, 40, 60, 80, 100],
labels=['Molto bassa', 'Bassa', 'Media', 'Alta', 'Molto alta']
)
/tmp/ipykernel_1179158/3928220547.py:2: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['classe_sostenibilita'] = pd.cut(
In [27]:
plt.figure(figsize=(10, 6))
sns.histplot(df['indice_sostenibilita_ambientale'], bins=20)
plt.title('Distribuzione dell\'indice di sostenibilità ambientale urbana')
plt.xlabel('Indice (0-100)')
plt.ylabel('Numero di celle')
plt.show()
In [28]:
plt.figure(figsize=(10, 6))
counts = df['classe_sostenibilita'].value_counts().sort_index()
plt.bar(counts.index, counts.values)
plt.title('Distribuzione delle classi di sostenibilità ambientale')
plt.xlabel('Classe di sostenibilità')
plt.ylabel('Numero di celle')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
3. INTEGRAZIONE CON DATI DEMOGRAFICI E ANALISI DELLE CORRELAZIONI¶
In [29]:
# Verifico se ci sono dati demografici
demo_cols = [col for col in df.columns if 'ISTAT||P' in col and '__21' in col]
In [30]:
# Correlazione tra indici e popolazione
correlations = {
'Indice di urbanizzazione': df[['indice_urbanizzazione', 'ISTAT||POP_TOT__21']].corr().iloc[0,1],
'Indice potenziale verde': df[['indice_potenziale_verde', 'ISTAT||POP_TOT__21']].corr().iloc[0,1],
'Indice sostenibilità ambientale': df[['indice_sostenibilita_ambientale', 'ISTAT||POP_TOT__21']].corr().iloc[0,1]
}
In [31]:
plt.figure(figsize=(10, 6))
plt.bar(correlations.keys(), correlations.values())
plt.title('Correlazione tra indici e popolazione')
plt.ylabel('Coefficiente di correlazione')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
In [32]:
# Correlazione tra indici
correlation_matrix = df[['indice_urbanizzazione', 'indice_potenziale_verde',
'indice_sostenibilita_ambientale']].corr()
plt.figure(figsize=(8, 6))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Matrice di correlazione tra indici')
plt.tight_layout()
plt.show()
4. IDENTIFICAZIONE DELLE AREE OTTIMALI PER ENERGIA RINNOVABILE¶
In [33]:
# Creazione indice per potenziale fotovoltaico
# Alto potenziale verde, bassa urbanizzazione, buona accessibilità
df['indice_potenziale_fotovoltaico'] = (
df['indice_potenziale_verde'] * 0.6 + # 60% potenziale verde
(100 - df['indice_urbanizzazione']) * 0.3 + # 30% aree non urbanizzate
df['accessibilita_norm'] * 0.1 # 10% accessibilità
) / 100 * 100 # Normalizzazione a 0-100
# Top 10% delle celle per potenziale fotovoltaico
threshold = df['indice_potenziale_fotovoltaico'].quantile(0.9)
top_cells = df[df['indice_potenziale_fotovoltaico'] >= threshold]
print(f"\nIdentificate {len(top_cells)} celle (top 10%) con alto potenziale per energia fotovoltaica")
print(f"Potenziale medio delle celle selezionate: {top_cells['indice_potenziale_fotovoltaico'].mean():.2f}/100")
Identificate 229 celle (top 10%) con alto potenziale per energia fotovoltaica Potenziale medio delle celle selezionate: 96.40/100
/tmp/ipykernel_1179158/2140658467.py:4: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['indice_potenziale_fotovoltaico'] = (
In [34]:
plt.figure(figsize=(10, 6))
sns.histplot(df['indice_potenziale_fotovoltaico'], bins=20)
plt.axvline(x=threshold, color='r', linestyle='--',
label=f'Soglia top 10% ({threshold:.2f})')
plt.title('Distribuzione dell\'indice di potenziale fotovoltaico')
plt.xlabel('Indice (0-100)')
plt.ylabel('Numero di celle')
plt.legend()
plt.show()
5. ANALISI CONSUMO DI SUOLO E IDENTIFICAZIONE AREE CRITICHE¶
In [35]:
# Identificazione aree ad alto consumo di suolo
urban_threshold = df['indice_urbanizzazione'].quantile(0.75)
high_urban_cells = df[df['indice_urbanizzazione'] >= urban_threshold]
print(f"\nIdentificate {len(high_urban_cells)} celle (25% più urbanizzate)")
print(f"Indice medio di urbanizzazione delle celle selezionate: {high_urban_cells['indice_urbanizzazione'].mean():.2f}%")
Identificate 572 celle (25% più urbanizzate) Indice medio di urbanizzazione delle celle selezionate: 69.37%
In [36]:
plt.figure(figsize=(10, 6))
sns.histplot(df['indice_urbanizzazione'], bins=20)
plt.axvline(x=urban_threshold, color='r', linestyle='--',
label=f'Soglia top 25% ({urban_threshold:.2f}%)')
plt.title('Distribuzione dell\'indice di urbanizzazione')
plt.xlabel('Percentuale di area urbanizzata')
plt.ylabel('Numero di celle')
plt.legend()
plt.show()
In [37]:
# Rapporto tra consumo di suolo e densità abitativa (se disponibile)
plt.figure(figsize=(10, 6))
plt.scatter(df['indice_urbanizzazione'], df['densita_abitativa'], alpha=0.5)
plt.title('Relazione tra consumo di suolo e densità abitativa')
plt.xlabel('Indice di urbanizzazione (%)')
plt.ylabel('Densità abitativa (ab/km²)')
plt.grid(True)
plt.show()
In [38]:
# Calcolo efficienza uso del suolo (abitanti/% area urbanizzata)
df['efficienza_uso_suolo'] = np.where(df['indice_urbanizzazione'] > 0,
df['densita_abitativa'] / df['indice_urbanizzazione'],
0)
plt.figure(figsize=(10, 6))
sns.histplot(df['efficienza_uso_suolo'].clip(0, df['efficienza_uso_suolo'].quantile(0.95)), bins=20)
plt.title('Distribuzione dell\'indice di efficienza dell\'uso del suolo')
plt.xlabel('Abitanti per unità di urbanizzazione')
plt.ylabel('Numero di celle')
plt.show()
/tmp/ipykernel_1179158/355514563.py:2: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['efficienza_uso_suolo'] = np.where(df['indice_urbanizzazione'] > 0,
6. SINTESI DEGLI INDICATORI PER LA CONFERENZA¶
In [39]:
# Creazione tabella di sintesi
summary_stats = pd.DataFrame({
'Indicatore': [
'Indice di urbanizzazione (%)',
'Indice di potenziale verde (0-100)',
'Indice di sostenibilità ambientale (0-100)',
'Indice di potenziale fotovoltaico (0-100)',
'Efficienza uso del suolo (ab/unità urbanizzazione)'
],
'Media': [
df['indice_urbanizzazione'].mean(),
df['indice_potenziale_verde'].mean(),
df['indice_sostenibilita_ambientale'].mean(),
df['indice_potenziale_fotovoltaico'].mean(),
df['efficienza_uso_suolo'].mean() if 'efficienza_uso_suolo' in df.columns else np.nan
],
'Mediana': [
df['indice_urbanizzazione'].median(),
df['indice_potenziale_verde'].median(),
df['indice_sostenibilita_ambientale'].median(),
df['indice_potenziale_fotovoltaico'].median(),
df['efficienza_uso_suolo'].median() if 'efficienza_uso_suolo' in df.columns else np.nan
],
'Dev. Std': [
df['indice_urbanizzazione'].std(),
df['indice_potenziale_verde'].std(),
df['indice_sostenibilita_ambientale'].std(),
df['indice_potenziale_fotovoltaico'].std(),
df['efficienza_uso_suolo'].std() if 'efficienza_uso_suolo' in df.columns else np.nan
]
})
print("\nSintesi degli indicatori per la conferenza:")
summary_stats
Sintesi degli indicatori per la conferenza:
Out[39]:
| Indicatore | Media | Mediana | Dev. Std | |
|---|---|---|---|---|
| 0 | Indice di urbanizzazione (%) | 19.942717 | 0.000000 | 31.280477 |
| 1 | Indice di potenziale verde (0-100) | 81.604457 | 100.000000 | 30.912257 |
| 2 | Indice di sostenibilità ambientale (0-100) | 68.900500 | 72.771544 | 16.393705 |
| 3 | Indice di potenziale fotovoltaico (0-100) | 76.636223 | 90.572073 | 26.287756 |
| 4 | Efficienza uso del suolo (ab/unità urbanizzazi... | 169.937432 | 0.000000 | 3709.193731 |
7. MAPPA DI PRIORITÀ PER INTERVENTI DI ENERGIA VERDE¶
Creazione dell'indice di priorità
Alto potenziale verde + alta densità abitativa + alta accessibilità
In [40]:
# Normalizzazione della densità abitativa (0-100)
max_dens = df['densita_abitativa'].quantile(0.95) # Uso il 95° percentile per evitare outlier
df['densita_norm_pos'] = (df['densita_abitativa'] / max_dens * 100).clip(0, 100)
/tmp/ipykernel_1179158/141740308.py:3: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['densita_norm_pos'] = (df['densita_abitativa'] / max_dens * 100).clip(0, 100)
In [41]:
# Calcolo indice di priorità
df['indice_priorita_energia_verde'] = (
df['indice_potenziale_verde'] * 0.5 + # 50% potenziale verde
df['densita_norm_pos'] * 0.3 + # 30% densità (positiva in questo caso)
df['accessibilita_norm'] * 0.2 # 20% accessibilità
) / 100 * 100 # Normalizzazione a 0-100
/tmp/ipykernel_1179158/2520647873.py:2: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['indice_priorita_energia_verde'] = (
In [42]:
# Classificazione in 5 classi di priorità
df['classe_priorita'] = pd.qcut(
df['indice_priorita_energia_verde'],
q=5,
labels=['Molto bassa', 'Bassa', 'Media', 'Alta', 'Molto alta']
)
/tmp/ipykernel_1179158/69077833.py:2: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` df['classe_priorita'] = pd.qcut(
In [43]:
plt.figure(figsize=(10, 6))
sns.histplot(df['indice_priorita_energia_verde'], bins=20)
plt.title('Distribuzione dell\'indice di priorità per interventi di energia verde')
plt.xlabel('Indice di priorità (0-100)')
plt.ylabel('Numero di celle')
plt.show()
Conclusioni¶
In [44]:
# Estrazione dei risultati numerici dagli indicatori per conclusioni basate sui dati
# Statistiche di base dei principali indicatori
stats = {
'Urbanizzazione': {
'media': df['indice_urbanizzazione'].mean(),
'mediana': df['indice_urbanizzazione'].median(),
'deviazione': df['indice_urbanizzazione'].std(),
'q25': df['indice_urbanizzazione'].quantile(0.25),
'q75': df['indice_urbanizzazione'].quantile(0.75)
},
'Potenziale Verde': {
'media': df['indice_potenziale_verde'].mean(),
'mediana': df['indice_potenziale_verde'].median(),
'deviazione': df['indice_potenziale_verde'].std(),
'q25': df['indice_potenziale_verde'].quantile(0.25),
'q75': df['indice_potenziale_verde'].quantile(0.75)
}
}
if 'indice_sostenibilita_ambientale' in df.columns:
stats['Sostenibilità Ambientale'] = {
'media': df['indice_sostenibilita_ambientale'].mean(),
'mediana': df['indice_sostenibilita_ambientale'].median(),
'deviazione': df['indice_sostenibilita_ambientale'].std(),
'q25': df['indice_sostenibilita_ambientale'].quantile(0.25),
'q75': df['indice_sostenibilita_ambientale'].quantile(0.75)
}
if 'efficienza_uso_suolo' in df.columns:
stats['Efficienza Uso Suolo'] = {
'media': df['efficienza_uso_suolo'].mean(),
'mediana': df['efficienza_uso_suolo'].median(),
'deviazione': df['efficienza_uso_suolo'].std(),
'q25': df['efficienza_uso_suolo'].quantile(0.25),
'q75': df['efficienza_uso_suolo'].quantile(0.75)
}
# Percentuale di aree con alto potenziale verde
high_potential = len(df[df['indice_potenziale_verde'] > 60]) / len(df) * 100
# Correlazione tra urbanizzazione e potenziale verde
urb_green_corr = df[['indice_urbanizzazione', 'indice_potenziale_verde']].corr().iloc[0,1]
# Aree prioritarie identificate
if 'indice_priorita_energia_verde' in df.columns:
priority_areas = len(df[df['indice_priorita_energia_verde'] > df['indice_priorita_energia_verde'].quantile(0.8)])
priority_pct = priority_areas / len(df) * 100
# Analisi delle aree altamente urbanizzate
high_urban = len(df[df['indice_urbanizzazione'] > 50]) / len(df) * 100
# Output dei risultati
print("\n=== CONSIDERAZIONI FINALI BASATE SUI DATI ===\n")
print(f"1. MODELLI DI URBANIZZAZIONE E POTENZIALE VERDE")
print(f" • L'indice di urbanizzazione medio è {stats['Urbanizzazione']['media']:.1f}%, con una mediana di {stats['Urbanizzazione']['mediana']:.1f}%")
print(f" • Il 25% delle aree ha un indice di urbanizzazione superiore al {stats['Urbanizzazione']['q75']:.1f}%")
print(f" • {high_urban:.1f}% delle celle analizzate presenta un'urbanizzazione superiore al 50%")
print(f" • Il potenziale verde medio è {stats['Potenziale Verde']['media']:.1f}/100, con una mediana di {stats['Potenziale Verde']['mediana']:.1f}")
print(f" • {high_potential:.1f}% delle aree presenta un alto potenziale per l'energia verde (>60/100)")
print(f" • La correlazione tra urbanizzazione e potenziale verde è {urb_green_corr:.2f}, indicando una {abs(urb_green_corr) > 0.5 and 'forte' or 'moderata'} relazione {urb_green_corr < 0 and 'negativa' or 'positiva'}")
if 'Efficienza Uso Suolo' in stats:
print(f"\n2. EFFICIENZA DELL'USO DEL SUOLO")
print(f" • L'efficienza media dell'uso del suolo è {stats['Efficienza Uso Suolo']['media']:.1f} abitanti per unità di urbanizzazione")
print(f" • Il 25% delle aree più efficienti presenta valori superiori a {stats['Efficienza Uso Suolo']['q75']:.1f}")
print(f" • La distribuzione mostra una deviazione standard di {stats['Efficienza Uso Suolo']['deviazione']:.1f}, indicando una {stats['Efficienza Uso Suolo']['deviazione'] > stats['Efficienza Uso Suolo']['media'] and 'alta' or 'moderata'} variabilità")
if 'indice_priorita_energia_verde' in df.columns:
print(f"\n3. AREE PRIORITARIE PER INTERVENTI DI ENERGIA VERDE")
print(f" • Sono state identificate {priority_areas} celle ad alta priorità, pari al {priority_pct:.1f}% del territorio analizzato")
print(f" • Queste aree combinano alto potenziale verde, buona accessibilità e densità abitativa significativa")
# Aggiungere altri insight specifici se disponibili
if 'classe_potenziale_verde' in df.columns:
verde_counts = df['classe_potenziale_verde'].value_counts(normalize=True) * 100
print(f"\n4. DISTRIBUZIONE DEL POTENZIALE VERDE")
for classe, percentuale in verde_counts.sort_index().items():
print(f" • {classe}: {percentuale:.1f}% delle aree")
print("\nRACCOMANDAZIONI BASATE SUI DATI:")
print(f"• Prioritizzare interventi di energia verde nelle {priority_areas} celle identificate come ad alta priorità")
print(f"• Aumentare l'efficienza dell'uso del suolo nelle aree urbanizzate, specialmente nel 25% con valori inferiori a {stats['Efficienza Uso Suolo']['q25']:.1f}" if 'Efficienza Uso Suolo' in stats else "")
print(f"• Sviluppare progetti pilota di comunità energetiche nel {high_potential:.1f}% delle aree con alto potenziale verde")
print(f"• Implementare strategie di densificazione urbana sostenibile nelle aree con indice di urbanizzazione tra 30% e 50%, bilanciando sviluppo e conservazione del potenziale verde")
=== CONSIDERAZIONI FINALI BASATE SUI DATI === 1. MODELLI DI URBANIZZAZIONE E POTENZIALE VERDE • L'indice di urbanizzazione medio è 19.9%, con una mediana di 0.0% • Il 25% delle aree ha un indice di urbanizzazione superiore al 32.8% • 18.6% delle celle analizzate presenta un'urbanizzazione superiore al 50% • Il potenziale verde medio è 81.6/100, con una mediana di 100.0 • 79.2% delle aree presenta un alto potenziale per l'energia verde (>60/100) • La correlazione tra urbanizzazione e potenziale verde è -1.00, indicando una forte relazione negativa 2. EFFICIENZA DELL'USO DEL SUOLO • L'efficienza media dell'uso del suolo è 169.9 abitanti per unità di urbanizzazione • Il 25% delle aree più efficienti presenta valori superiori a 42.5 • La distribuzione mostra una deviazione standard di 3709.2, indicando una alta variabilità 3. AREE PRIORITARIE PER INTERVENTI DI ENERGIA VERDE • Sono state identificate 457 celle ad alta priorità, pari al 20.0% del territorio analizzato • Queste aree combinano alto potenziale verde, buona accessibilità e densità abitativa significativa 4. DISTRIBUZIONE DEL POTENZIALE VERDE • Molto basso: 7.0% delle aree • Basso: 5.5% delle aree • Medio: 6.6% delle aree • Alto: 7.0% delle aree • Molto alto: 74.0% delle aree RACCOMANDAZIONI BASATE SUI DATI: • Prioritizzare interventi di energia verde nelle 457 celle identificate come ad alta priorità • Aumentare l'efficienza dell'uso del suolo nelle aree urbanizzate, specialmente nel 25% con valori inferiori a 0.0 • Sviluppare progetti pilota di comunità energetiche nel 79.2% delle aree con alto potenziale verde • Implementare strategie di densificazione urbana sostenibile nelle aree con indice di urbanizzazione tra 30% e 50%, bilanciando sviluppo e conservazione del potenziale verde
In [45]:
print('CONCLUSIONI PER RISOLUZIONE 8')
print("L'analisi del territorio mostra un pattern di urbanizzazione eterogeneo, con un valore medio del 20% ma una mediana di 0%, suggerendo che molte aree rimangono prevalentemente non urbanizzate mentre altre presentano un'intensa edificazione, come conferma il dato che quasi il 19% delle celle ha un'urbanizzazione superiore al 50%.")
print("È evidente una forte relazione inversamente proporzionale (correlazione -1.00) tra urbanizzazione e potenziale verde, confermando che le aree meno urbanizzate mantengono maggiore capacità di sviluppo sostenibile. Questo è ulteriormente supportato dal fatto che quasi l'80% del territorio presenta un alto potenziale per l'energia verde (>60/100).")
print("L'efficienza dell'uso del suolo mostra una distribuzione estremamente variabile (deviazione standard di 3709.2), con alcune aree che ottimizzano il rapporto tra densità abitativa e superficie urbanizzata mentre altre appaiono significativamente sottoutilizzate, suggerendo opportunità di densificazione in alcune zone.")
print("La classificazione del territorio per potenziale verde rivela una distribuzione fortemente sbilanciata verso la categoria 'molto alto' (74% delle aree), indicando ampie opportunità per investimenti in energia rinnovabile e infrastrutture verdi nella maggior parte del territorio analizzato.")
print("L'identificazione di 457 celle ad alta priorità (20% del territorio) che combinano alto potenziale verde, buona accessibilità e densità abitativa significativa rappresenta un'opportunità strategica per interventi che possano massimizzare i benefici sociali ed ecologici, rivitalizzando aree già popolate attraverso soluzioni energetiche sostenibili.")
print("Questi risultati suggeriscono l'opportunità di politiche di pianificazione urbana orientate alla 'crescita interna', incentivando lo sviluppo nelle aree già urbanizzate per preservare il considerevole potenziale verde esistente, mentre si promuovono simultaneamente interventi di efficientamento energetico e sviluppo di comunità energetiche nelle aree prioritarie identificate.")
CONCLUSIONI PER RISOLUZIONE 8 L'analisi del territorio mostra un pattern di urbanizzazione eterogeneo, con un valore medio del 20% ma una mediana di 0%, suggerendo che molte aree rimangono prevalentemente non urbanizzate mentre altre presentano un'intensa edificazione, come conferma il dato che quasi il 19% delle celle ha un'urbanizzazione superiore al 50%. È evidente una forte relazione inversamente proporzionale (correlazione -1.00) tra urbanizzazione e potenziale verde, confermando che le aree meno urbanizzate mantengono maggiore capacità di sviluppo sostenibile. Questo è ulteriormente supportato dal fatto che quasi l'80% del territorio presenta un alto potenziale per l'energia verde (>60/100). L'efficienza dell'uso del suolo mostra una distribuzione estremamente variabile (deviazione standard di 3709.2), con alcune aree che ottimizzano il rapporto tra densità abitativa e superficie urbanizzata mentre altre appaiono significativamente sottoutilizzate, suggerendo opportunità di densificazione in alcune zone. La classificazione del territorio per potenziale verde rivela una distribuzione fortemente sbilanciata verso la categoria 'molto alto' (74% delle aree), indicando ampie opportunità per investimenti in energia rinnovabile e infrastrutture verdi nella maggior parte del territorio analizzato. L'identificazione di 457 celle ad alta priorità (20% del territorio) che combinano alto potenziale verde, buona accessibilità e densità abitativa significativa rappresenta un'opportunità strategica per interventi che possano massimizzare i benefici sociali ed ecologici, rivitalizzando aree già popolate attraverso soluzioni energetiche sostenibili. Questi risultati suggeriscono l'opportunità di politiche di pianificazione urbana orientate alla 'crescita interna', incentivando lo sviluppo nelle aree già urbanizzate per preservare il considerevole potenziale verde esistente, mentre si promuovono simultaneamente interventi di efficientamento energetico e sviluppo di comunità energetiche nelle aree prioritarie identificate.
Export¶
In [46]:
cols_indicatori = [
# 'indice_urbanizzazione',
# 'potenziale_base',
# 'bonus_aree_naturali',
# 'bonus_aree_agricole',
# 'indice_potenziale_verde',
# 'classe_potenziale_verde',
# 'accessibilita_15min',
# 'accessibilita_30min',
# 'indice_accessibilita',
# 'accessibilita_norm',
# 'verde_norm',
# 'densita_abitativa',
# 'densita_norm',
'indice_sostenibilita_ambientale',
# 'classe_sostenibilita',
'indice_potenziale_fotovoltaico',
'efficienza_uso_suolo',
# 'densita_norm_pos',
# 'indice_priorita_energia_verde',
# 'classe_priorita'
]
In [47]:
map_indicatori = {
'indice_sostenibilita_ambientale': 'ISA',
'indice_potenziale_fotovoltaico': 'IPF',
'efficienza_uso_suolo': 'ESS',
}
In [48]:
df_base = df.copy()
Output con classi
In [49]:
n_classes = 5
new_columns = {}
for col in cols_indicatori:
# Calcola i natural breaks di Jenks per la classificazione
breaks = jenks_breaks(df[col].values, n_classes=n_classes)
# Crea le classi usando pd.cut ma salvale in un dizionario temporaneo
labels = [i+1 for i in range(len(breaks)-1)]
temp_series = pd.cut(
df[col],
bins=breaks,
labels=labels,
include_lowest=True
)
# Salva il risultato convertito in int nel dizionario
new_columns[col] = temp_series.astype(int)
# Aggiorna il dataframe una sola volta con tutte le colonne
df = pd.concat([df.drop(columns=cols_indicatori), pd.DataFrame(new_columns)], axis=1)
df.rename(columns=map_indicatori, inplace=True)
gdf = gpd.GeoDataFrame(df[list(map_indicatori.values()) + ['geometry', f'h3_{resolution:02}']], geometry='geometry', crs=32632)
gdf['geometry'] = gdf['geometry'].centroid
gdf.to_crs(4326).to_file(os.path.join(out_path, f'grid_{resolution:02}_pt_tavolo4.geojson'), driver="GeoJSON")
Output con valori assoluti
In [50]:
n_classes = 5
df = df_base.copy()
df.rename(columns=map_indicatori, inplace=True)
gdf = gpd.GeoDataFrame(df[list(map_indicatori.values()) + ['geometry', f'h3_{resolution:02}']], geometry='geometry', crs=32632)
gdf['geometry'] = gdf['geometry'].centroid
cols_indicatori = map_indicatori.values()
asc3 = gpd.read_file(os.path.join(ilab_path,'ROMA','DATA','ASC_21', 'ASC_Liv_3_WGS84.shp'))
asc3 = asc3[asc3['PRO_COM']==58091].copy()
asc3_ind = asc3.sjoin(gdf)
aggs = {col:'mean' for col in cols_indicatori}
asc3_ind_g = asc3_ind.groupby('DEN_ASC3', as_index=False).agg(aggs)
for col in cols_indicatori:
# Calcola i natural breaks di Jenks per la classificazione
breaks = jenks_breaks(asc3_ind_g[col].values, n_classes=n_classes)
# Crea una nuova colonna con le classi di Jenks
labels = [i+1 for i in range(len(breaks)-1)]
asc3_ind_g.loc[:, f'{col}_cls'] = pd.cut(
asc3_ind_g[col],
bins=breaks,
labels=labels,
include_lowest=True
)
asc3_ind_g[f'{col}_cls'] = asc3_ind_g[f'{col}_cls'].astype(int)
asc3_out = asc3.merge(asc3_ind_g, how='left', on='DEN_ASC3')
asc3_out.to_crs(4326).to_file(os.path.join(out_path, f'asc3_tavolo4.geojson'), driver="GeoJSON")