Elezioni Regionali: Emilia-Romagna del 17-18 novembre 2024¶
Dal sito eligendo... https://elezioni.interno.gov.it/risultati/20241117/regionali/elenchi/italia/08
In [1]:
import os
import requests
import json
import folium
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import geopandas as gpd
import pandas as pd
from datetime import datetime
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
# from itables import init_notebook_mode, show
# init_notebook_mode(all_interactive=True)
In [2]:
id_regione = '08'
regione_sel = 'emilia'
data_ele = '20241117'
In [3]:
elezioni_path = os.path.join(os.path.expanduser('~'),'ILAB_DATA',f'ELEZIONI_{regione_sel.upper()}_2024')
In [4]:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Referer': 'https://elezioni.interno.gov.it/'
}
Reperimento informazioni territoriali (comuni della regione)¶
In [5]:
url = f'https://elezioni.interno.gov.it/mappe/comuni_{id_regione}.geojson'
comuni = gpd.read_file(url)
comuni = comuni.to_dict('records')
In [6]:
variables = [ 'dt_ele', 'cod_sez', 'desc_sez', 'desc_com', 'ele_m', 'ele_f',
'ele_t', 'vot_m', 'vot_f', 'vot_t', 'perc_vot', 'sz_perv', 'sz_tot',
'fine_rip', 'sk_bianche', 'sk_nulle','sk_contestate', 'tot_vot_lis',
'non_valid', 'osp', 'data_prec_elez','circ_sto', 'reg_sto', 'prov_sto', 'comu_sto', 'sez_sto']
Scraping dei dati degli scrutini¶
In [7]:
scrutini_path = os.path.join(elezioni_path,f'CSV/scrutini_{regione_sel}.csv')
if not os.path.exists(scrutini_path):
n_comuni = len(comuni)
errors = 0
comuni_out = []
for i, comune_key in enumerate(comuni):
comune_name = comune_key['name']
minint_elettorale = comune_key['minint_elettorale']
cod_reg = minint_elettorale[:3]
cod_prov = minint_elettorale[3:6]
cod_com = minint_elettorale[6:]
print(f'Sto elaborando {comune_name} ({i+1}/{n_comuni})')
try:
api_endpoint = f'https://eleapi.interno.gov.it/siel/PX/scrutiniR/DE/{data_ele}/TE/07/RE/{id_regione}/PR/{cod_prov}/CM/{cod_com}'
response = requests.get(api_endpoint, verify=True, headers=headers).json()
comune = {k:v for k,v in response['int'].items() if k in variables}
comune['cod_prov'] = cod_prov
comune['cod_com'] = cod_com
comune['minint_elettorale'] = minint_elettorale
comune['dt_ele'] = datetime.strptime(str(comune['dt_ele']),'%Y%m%d%H%M%S').strftime('%Y-%m-%d')
if comune['ele_t'] < comune['vot_t']:
comune['perc_vot'] = '0'
comune['perc_vot'] = float(comune['perc_vot'].replace(',','.'))
for p in response['cand']:
nome_cand = p['nome'] + ' ' + p['cogn']
comune[f'{nome_cand}_voti'] = p['voti']
comune[f'{nome_cand}_perc'] = float(p['perc'].replace(',','.'))
comuni_out.append(comune)
except Exception as e:
print(e)
errors+=1
df = pd.DataFrame(comuni_out)
print(df.shape)
df.to_csv(scrutini_path, sep=';',index=False)
Visualizzazione dei dati¶
In [8]:
comune_sel = 'BOLOGNA'
In [9]:
types = {'cod_com':str, 'cod_prov':str,'minint_elettorale':str}
df = pd.read_csv(os.path.join(elezioni_path,f'CSV/scrutini_{regione_sel}.csv'), dtype=types, sep=';')
url = f'https://elezioni.interno.gov.it/mappe/comuni_{id_regione}.geojson'
comuni = gpd.read_file(url)
Chi ha vinto?
In [10]:
lista_candidati = [cand for cand in df.columns if '_voti' in cand]
sums = list()
for cand in lista_candidati:
d = {'candidato':cand.replace('_voti',''),
'voti':df[cand].sum()}
sums.append(d)
sums = pd.DataFrame(sums)
sums['r'] = sums['voti'].rank(ascending=False)
candidati = sums['candidato'].to_list()
candidato1 = candidati[0]
candidato2 = candidati[1]
In [11]:
df[df['desc_com']==comune_sel].to_dict('records')
Out[11]:
[{'dt_ele': '2024-11-17',
'desc_com': 'BOLOGNA',
'ele_m': 147381,
'ele_f': 162396,
'ele_t': 309777,
'vot_m': 78037,
'vot_f': 85970,
'vot_t': 164007,
'perc_vot': 52.94,
'sz_tot': 445,
'fine_rip': 'S',
'sk_bianche': 666,
'sk_nulle': 1863,
'sk_contestate': 41,
'tot_vot_lis': 146364,
'non_valid': nan,
'data_prec_elez': 20200126000000.0,
'reg_sto': 8.0,
'prov_sto': 13.0,
'comu_sto': 60.0,
'circ_sto': 13.0,
'cod_prov': '013',
'cod_com': '0060',
'minint_elettorale': '1080130060',
'ELENA UGOLINI_voti': 51567,
'ELENA UGOLINI_perc': 31.94,
'MICHELE DE PASCALE_voti': 102589,
'MICHELE DE PASCALE_perc': 63.55,
'LUCA TEODORI_voti': 1733,
'LUCA TEODORI_perc': 1.07,
'FEDERICO SERRA_voti': 5548,
'FEDERICO SERRA_perc': 3.44}]
Selezione delle colonne del dataset degli scrutini¶
In [12]:
df = df[['minint_elettorale',f'{candidato1}_voti',f'{candidato1}_perc',f'{candidato2}_voti',f'{candidato2}_perc']].copy()
Attribuzione delle informazioni geografiche¶
In [13]:
df_adv = comuni[['name','minint_elettorale','geometry','com_istat_code']].merge(df, left_on='minint_elettorale', right_on='minint_elettorale')
Suddivisione nei due dataset per maggioranza dei voti¶
In [14]:
cand1 = df_adv[df_adv[f'{candidato1}_voti']>=df_adv[f'{candidato2}_voti']].copy()
cand2 = df_adv[df_adv[f'{candidato1}_voti']<df_adv[f'{candidato2}_voti']].copy()
Visualizzazione su base comunale¶
In [15]:
m = cand1.explore(column=f'{candidato1}_perc',cmap='Blues', name=f'{candidato1.title()}')
m = cand2.explore(m=m,column=f'{candidato2}_perc', cmap='Reds', name=f'{candidato2.title()}')
folium.LayerControl().add_to(m)
m
Out[15]:
Make this Notebook Trusted to load map: File -> Trust Notebook
Utilizzo della tecnica "sample_points"¶
Creazione di un numero casuale di punti all'interno dei poligoni dei comuni, il numero di punti è proporzionale alla percentuale di voti ottenuta dal candidato
In [16]:
seed = 1234512345
p_voti = cand1[f'{candidato1}_perc'].mul(1).astype(int).values
cand1['p_voti'] = cand1.sample_points(p_voti,rng=seed)
cand1_p = cand1.set_geometry('p_voti')
p_voti = cand2[f'{candidato2}_perc'].mul(1).astype(int).values
cand2['p_voti'] = cand2.sample_points(p_voti,rng=seed)
cand2_p = cand2.set_geometry('p_voti')
Visualizzazione¶
In [17]:
m = cand1_p.explode(index_parts=True).explore(column=f'{candidato1}_perc',cmap='Blues',name=f'{candidato1}'.title())
m = cand2_p.explode(index_parts=True).explore(m=m,column=f'{candidato2}_perc', cmap='Reds', name=f'{candidato2}'.title())
folium.LayerControl().add_to(m)
m
Out[17]:
Make this Notebook Trusted to load map: File -> Trust Notebook