Python, Parquets & Opendata (part 1)

Il Fondo di Garanzia #FdG è uno strumento messo a disposizione dallo Stato italiano per facilitare l’accesso al credito alle piccole e medie imprese (PMI) e ai professionisti. Nella sezione…

Aiuti
FdG
Python
Opendata
Autore/Autrice

Paolo Volterra

Data di Pubblicazione

10 novembre 2024

1 Il Fondo di Garanzia e Python

#FdG è uno strumento messo a disposizione dallo Stato italiano per facilitare l’accesso al credito alle piccole e medie imprese (PMI) e ai professionisti.

Nella sezione “Amministrazione trasparente” del sito vengono pubblicati gli opendata in file mensili in formato csv e xls

I due file più recenti vengono aggiornati due volte a settimana durante il mese di competenza.

S.e., i file “storici” non vengono più aggiornati una volta passati al mese successivo.

Questa (buona) impostazione evita di dover scaricare ogni volta tutti i 100 e più file e doverli rilavorare per verificare se ci sono state modiifiche “retroattive”

1.1 Concentriamoci ora sui csv

La struttura del file è sempre la stessa e contiene 14 colonne:

  • Ragione sociale e forma giuridica dell’impresa
  • Codice fiscale dell’impresa
  • Tipologia di intervento
  • Importo massimo garantito (euro) (con i punti per le migliaia e la virgola decimale)
  • Riserva / Sezione speciale
  • Data di delibera di concessione della garanzia
  • Importo del finanziamento (con i punti per le migliaia e la virgola decimale)
  • Codice ATECO a 6 cifre dell’attività dell’impresa
  • Anno di riferimento della classificazione ATECO (non so a cosa possa servire)
  • Settore economico
  • Regione di utilizzo
  • Provincia (sigla) di utilizzo
  • Comune di utilizzo
  • Tipo di processo

In questo studio voglio:

  1. collegarmi automaticamente ai dati, senza fare download manuali;
  2. fare ETL;
  3. salvarli in formato Parquet per un’interrogazione molto più veloce

Il punto 2) e 3) sono i più interessanti: un corretto settaggio permette di importare efficientemente le informazioni

1.2 Import librerie

import os
from io import StringIO
import pandas as pd
import requests
import duckdb
pd.set_option('display.float_format', lambda x: '%.2f' % x)

1.3 Collegamento al file online

proviamo a lavorare il file di novembre 2024

file = ("2024-M11")
url='https://www.fondidigaranzia.it/wp-content/uploads/amm_aperta/'+file+'.csv'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'}
s=requests.get(url, headers= headers).text

1.4 ETL

date_column = ['delibera']
df = pd.read_csv(StringIO(s), header=0, sep=',', quotechar='"',
names=['impresa', 'CF','intervento','garantito','riserva','delibera',
       'finanziamento','ATECO','anno','settore','regione','prov',
       'comune','processo'],
       encoding='utf-8', 
       decimal="," , 
       thousands="." , 
       parse_dates=date_column, 
       dayfirst=True, 
       na_filter = False, 
       skipinitialspace=True)df['ATECO'] = df['ATECO'].astype(str)
df['anno'] = df['anno'].astype(str)
df['intervento'] = df['intervento'].astype(str)
df['CF'] = df['CF'].astype(str)

Le accortezze qui sono:

  • l’import dei valori numerici, che contengono il divisore delle migliaia e la virgola per i decimali; impostazioni che stonano con lo standard internazionale
  • la ridenominazione automatica delle colonne
  • la sterelizzazione della sigla “NA” per i Nan, in modo che non sia interpretata come provincia partenopea
  • l’annullamento di spazi inutili

La prima colonna contiene due valori (Ragione sociale e forma giuridica dell’impresa) che potrebbero essere facilmente separati ricorrendo ad uno “split”, utilizzando l’ultima virgola come separatore

df[['impresa','NG']] = df['impresa'].str.split(',', n=1, expand=True)

Ricordiamoci poi che il codice fiscale è un valore di 11 caratteri nel caso di società e di 16 caratteri nel caso di ditte individuali.

In ogni caso, come per la Partita Iva, si tratta di una stringa alfanumerica e non di un numero.

Se lo trattassimo come numero, perderemmo lo (gli) zero (i) iniziale (i)

df[df.isna().any(axis=1)]

con questo comando vediamo se ci sono stati errori (…)

Se non compare nulla, tutto è andato ok

1.5 Salvataggio in Parquet

df.to_parquet('D:\\duckdb\\files\\FdG\\FdG_'+file+'.parquet')

Il salvataggio in Parquet ha 2 vantaggi:

  • riduce lo spazio (1:5)
  • è performante nelle query (usate DuckDB!)

A questo punto abbiamo salvato nella directory un file Parquet molto più leggerlo di quello iniziale e lo abbiamo adattato per analisi successive.

Nel tempo la directory finisce per essere un Database: con Python potrai direttamente decidere quali file considerare nelle analisi

  • “select * from FgD_2024*.parquet “ per tutto il 2024
  • “select * from FgD_2024-M11.parquet” per novembre 2024
  • “select * from *.parquet” per tutti i files salvati

1.6 Un unico DB

Volendo, si puòrealizzare un unico file parquet come merge di tutti i precedenti ( cosa che un tempo facevo)

conn = duckdb.connect(database='D:/files/FdG.duckdb', read_only=False)
os.chdir('D:/')
DB ='D:/FdG.duckdb'
conn.execute(f'''CREATE TABLE FdG AS SELECT * FROM read_parquet('D:/duckdb/files/FdG/*.parquet');''').df()

1.7 Addendum

Prima del covid, i file csv:

  • erano trimestrali e non mensili
  • contenevano un’ulteriore colonna (inutile)
Torna in cima