Analisi dell’EDA sulla qualità dell’acqua in Python e analisi della potabilità
Analisi dell'EDA sulla qualità dell'acqua e potabilità in Python
Comprensione delle tecniche di analisi e visualizzazione dei dati
Riuscire a fornire abbastanza acqua potabile fresca è un requisito fondamentale. Nel dibattito sul cambiamento climatico, una delle sfide più grandi è garantire abbastanza acqua dolce per sopravvivere. La qualità dell’acqua è una grande preoccupazione che interessa tutte le specie. Solo circa il tre percento dell’acqua della Terra è acqua dolce. Di questo, solo l’1,2 percento può essere utilizzato come acqua potabile, mentre il resto è bloccato nei ghiacciai, nelle calotte polari e nel permafrost o sepolto in profondità nel terreno. Utilizzare un approccio basato sui dati per valutare le caratteristiche che influenzano la qualità dell’acqua potrebbe migliorare notevolmente la nostra comprensione di ciò che rende l’acqua potabile.
Al livello più elementare, la potabilità dell’acqua è legata alla sicurezza dell’acqua. Le tecniche di analisi dei dati possono essere utilizzate per esaminare questa caratteristica obiettivo. Emergono altre domande che sono al di fuori della nostra attuale revisione:
Possiamo consumare tutti i tipi di acqua dolce?
Quale percentuale dell’acqua dolce nel mondo può essere accessibile?
- Analisi dei dati umanitari Tabelle non strutturate di Excel con l’interprete di codice ChatGPT
- ChatGPT ci sta superando? Un’esplorazione attraverso la lente del Test di Turing
- OpenAI querelata dagli autori per aver utilizzato i loro libri per addestrare ChatGPT senza consenso
L’acquifero è aumentato con l’aumento del livello del mare?
In questo articolo, intraprenderemo un viaggio con un piccolo set di dati sulla qualità dell’acqua. Dai dati, cercheremo di trovare insiemi nascosti con tecniche di analisi dei dati utilizzando pandas e numpy. Per le visualizzazioni dei dati, verranno utilizzate le librerie matplotlib e seaborn. Saranno impiegate una serie di tecniche di analisi esplorativa dei dati (EDA) per fornire ulteriore chiarezza sulla qualità dei dati.
Ogni visualizzazione dei dati avrà lo scopo di evidenziare diverse caratteristiche dei dati. Forniranno inoltre all’utente modelli da applicare ad altre sfide.
Dataset
Per questa analisi, il dataset sulla qualità dell’acqua è stato preso da Kaggle¹.
Qualità dell’acqua
Potabilità dell’acqua potabile
www.kaggle.com
È stato utilizzato un notebook Jupyter con codice Python per l’elaborazione.
import sysprint(sys.version) # visualizza la versione di python installata
Dopo aver eseguito lo script sopra, verrà mostrato un output che indica che è stata utilizzata la versione 3.7.10 di Python. Per poter replicare i risultati che seguono, gli utenti dovrebbero assicurarsi di utilizzare Python 3 all’interno dell’ambiente di lavoro.
Comprensione dei dati
Prima di tutto, dobbiamo comprendere i dati con cui stiamo lavorando. Poiché il formato del file è un file csv, verrà utilizzata l’istruzione standard di importazione di pandas utilizzando read_csv.
# Importa il dataset da esaminare come un DataFrame
df = pd.read_csv("../input/water-potability/water_potability.csv")
# Esamina le prime cinque osservazioni
df.head()
Dopo aver importato i dati, il codice assegna alla variabile df i risultati di output del DataFrame dal metodo pandas.
Come per qualsiasi dataset che si elabora, la revisione di un campione di record aiuta a ottenere familiarità. Un DataFrame ha un gran numero di metodi associati ad esso, con l’API di pandas che è una grande risorsa da utilizzare. All’interno dell’API può essere utilizzato il metodo head. L’output 1.1 mostra per default le prime 5 righe del DataFrame. Per produrre un numero maggiore di righe da visualizzare, sarebbe necessario un valore numerico all’interno delle parentesi. Due alternative potrebbero essere applicate per campionare il DataFrame con i) sample (df.sample()) selezionando righe casuali dall’indice, o ii) tail (df.tail()) selezionando le ultime n righe dall’indice.

Quando si esegue un qualsiasi metodo, le parentesi vengono incluse dopo il nome del metodo, consentendo all’interprete Python di produrre il risultato.
Visualizzare la memoria di un DataFrame può essere un’operazione comune, soprattutto quando sono coinvolti vincoli di memoria. Un esempio è quando il dataset da importare potrebbe essere più grande della memoria disponibile all’interno della sessione Python. Utilizzando la libreria pandas, viene creato un DataFrame in memoria, quindi gli utenti dovrebbero capire quale memoria può essere utilizzata durante l’esecuzione di queste operazioni di elaborazione.
# Mostra informazioni sul DataFrame - contiene dettagli sulla memoria
df.info(memory_usage="deep")
Il codice sopra può essere utilizzato come metodo per visualizzare l’output 1.2. Con l’inclusione della parola chiave memory_usage, l’interprete Python è costretto a fare una ricerca più approfondita per capire l’utilizzo della memoria che viene visualizzato di seguito. Un’opzione predefinita farebbe una ricerca generale per capire, quindi se è necessaria precisione nella valutazione, assicurarsi che la frase chiave sopra sia applicata.

Dai risultati mostrati nell’output 1.2, può mostrare una serie di dettagli, dai nomi delle colonne e i tipi di dati, fino alla conferma della classe della variabile e al numero di valori non nulli. Possiamo vedere che vengono mostrate 3.276 righe all’interno dell’intera tabella. Tuttavia, per la colonna Sulfate, sono presenti solo 2.495 valori non nulli. Pertanto, è possibile esaminare un certo numero di valori mancanti per capire se c’è un pattern per queste voci mancanti con altre colonne. Successivamente, esamineremo una tecnica di visualizzazione dei dati nell’articolo che può aiutare con il riconoscimento di pattern.
Dopo l’importazione precedente, gli utenti potrebbero aver modificato il Dtype di una colonna se le opzioni predefinite non erano quelle previste. I risultati sopra mostrano che per i numeri decimali viene applicato il Dtype float, con il numero intero mostrato come int. Inoltre, è stato incluso il tipo di memoria byte più grande per queste colonne numeriche al fine di fornire la copertura completa dei valori di input potenziali. Molte volte gli utenti dovrebbero valutare se questi Dtypes contengono la gamma corretta di valori e se ci si aspetta un intervallo più piccolo in futuro, quindi potrebbe essere assegnato un valore di byte più piccolo. Applicando questa logica si potrebbe aumentare l’efficienza della memoria del DataFrame e aiutare con le prestazioni durante l’elaborazione.
Una caratteristica mostrata dal metodo info sopra che può essere esaminata da molti altri metodi è la struttura del DataFrame. Questi metadati permettono ai programmatori di esaminare i componenti di base del numero di righe e colonne.
# Forma del DataFrame - mostra una tupla di (#Righe, #Colonne)
print(df.shape)
# Trova il numero di righe all'interno di un DataFrame
print(len(df))
# Estrarre informazioni dalla tupla di forma
print(f'Numero di righe: {df.shape[0]} \nNumero di colonne: {df.shape[1]}')
Quando si chiama un attributo in Python come shape, non saranno necessarie le parentesi. Un attributo è un risultato di dati che può essere accessibile sia da una classe che dal suo oggetto. In precedenza abbiamo esaminato un metodo che è una funzione contenuta all’interno di una classe. Per ulteriori approfondimenti sui dettagli più piccoli, sarebbe necessario un approfondimento su come funzionano le dichiarazioni di classe in Python. Tuttavia, possiamo continuare con il codice utilizzato e mostrare che con l’output 1.3 sono stati visualizzati diversi valori.

La prima riga mostra l’output della forma che è una tupla, rappresentata da una parentesi con due valori. Dal codice mostrato sopra siamo in grado di accedere alle posizioni relative all’interno di questa tupla per visualizzare i valori della prima e della seconda posizione. Poiché Python utilizza una convenzione di indicizzazione a 0, il primo valore verrà restituito applicando il 0 tra parentesi quadre. Possiamo vedere che la tupla conteneva il numero di righe nella prima posizione, seguito dal numero di colonne nella seconda. Un metodo alternativo per trovare il numero di righe sarebbe utilizzare la funzione len, che restituisce la lunghezza del DataFrame.
Statistiche riassuntive
In questa sezione, iniziamo a esaminare i dettagli riassuntivi delle colonne del DataFrame. È disponibile un semplice metodo describe per eseguire un’analisi dei dati di alto livello delle colonne numeriche. Poiché il nostro DataFrame contiene solo colonne numeriche, vengono prodotte tutte le proprietà riassuntive. Quando sono presenti una combinazione di colonne carattere e numeriche, devono essere inclusi altri parametri di parole chiave per visualizzare gli output pertinenti.
# Esamina i dettagli riassuntivi di alto livello per ogni variabile
df.describe()
L’output 1.4 mostra i valori riassuntivi predefiniti per ogni colonna. I valori di conteggio possono essere interpretati come il conteggio dei valori non nulli. Con un totale inferiore al numero totale di righe nel DataFrame vengono mostrate colonne con valori mancanti. Per ogni variabile, possiamo vedere una gamma di valori. Potremmo utilizzare i quattro metodi dei momenti per capire i) Media, ii) Varianza, iii) Asimmetria e iv) Curtosi, basati sui dati visualizzati.

Avere una conoscenza esterna per capire le proprietà delle feature è anche cruciale durante la revisione dei dettagli di riepilogo. Sappiamo per esperienza che il valore del pH dovrebbe essere compreso tra 0 e 14. Se un valore dovesse cadere al di fuori di questo intervallo, i valori delle feature dovrebbero essere rivisti e corretti. Con i dati utilizzati per valutare la qualità dell’acqua, avere una media e una mediana (visualizzate dal 50° percentile) vicine a 7 è appropriato per le proprietà neutre dell’acqua.
Se ci sono un numero maggiore di feature nel DataFrame, l’output dal blocco di codice precedente può essere difficile da interpretare. L’output può essere distribuito orizzontalmente su un’ampia gamma che non è possibile visualizzare senza fare scorrere.
# Trasponi i dettagli di riepilogo - più facile per la revisione di un numero maggiore di featuredf.desribe().T
Avere la possibilità di trasporre l’output è un metodo utile da applicare. Nel blocco di codice sopra, concatenando il metodo T si ottiene l’output 1.5 sottostante. Ora è molto più facile per l’utente revisionare i nomi delle colonne visualizzati nell’indice delle righe con le metriche di riepilogo visualizzate come intestazioni di colonna. Questo piccolo aggiustamento al metodo describe funziona molto bene con un numero maggiore di colonne.

Per capire ulteriori dettagli sul metodo describe, possiamo interpretare la docstring utilizzando la funzione magica del notebook jupyter con un punto interrogativo.
# Funzione magica in jupyter per visualizzare la docstringdf.describe?
Aiuterà l’utente a revisionare i valori dei parametri predefiniti (keyword e posizionali) per qualsiasi metodo utilizzando questo approccio.

Output 1.6 fornisce il funzionamento interno del metodo per la revisione dell’utente. La gamma di valori predefiniti per ogni parametro, così come le definizioni, aiutano a facilitare l’applicazione del metodo. È disponibile una serie di funzioni magiche di jupyter che possono aiutare ad aumentare la produttività di un programmatore.
Valori mancanti
Come discusso in precedenza dalle metadati e dalle statistiche di riepilogo, ci sono alcuni valori mancanti all’interno del DataFrame. Per confermare se ciò è corretto, possiamo applicare il blocco di codice di seguito.
# Controlla i valori mancanti per colonnadf.isnull().sum()
Il codice ha concatenato il primo metodo isnull con il metodo sum per creare il numero di valori mancanti per colonna. Una valutazione isnull controllerà i valori non nulli in una colonna. Il metodo sum viene utilizzato per eseguire il conteggio. L’output 1.7 evidenzia che tre colonne mostrano valori mancanti.

Avere il conteggio totale delle righe con valori mancanti è un ottimo punto di partenza. Tuttavia, sarebbe meglio revisionare la proporzione di valori mancanti all’interno di una colonna.
# Proporzione dei valori mancanti per colonnadef isnull_prop(df): total_rows = df.shape[0] missing_val_dict = {} for col in df.columns: missing_val_dict[col] = [df[col].isnull().sum(), (df[col].isnull().sum() / total_rows)] return missing_val_dict# Applica il metodo per i valori mancantinull_dict = isnull_prop(df)print(null_dict.items())
Creare la funzione utente isnull_prop ci consente di creare un dizionario di valori per ogni colonna. Con questa funzione, abbiamo prodotto il valore di conteggio sopra, oltre a utilizzare l’attributo shape per comprendere la percentuale di valori mancanti.

L’output 1.8 ha mostrato un risultato difficile da visualizzare. Per assicurarci di non perdere il messaggio finale, potremmo produrre un DataFrame.
# Creare un dataframe con le informazioni sui valori mancanti
df_missing = pd.DataFrame.from_dict(null_dict, orient="index", columns=['mancanti', 'percentuale_mancanti'])
df_missing
Applicando la variabile dizionario al metodo pandas DataFrame renderà più facile comprendere le differenze per ogni colonna. L’output 1.9 include ora la colonna percentuale_mancanti. Potremmo ora applicare un valore di soglia per valutare se la percentuale di valori mancanti rientra nel nostro intervallo di aspettative per utilizzare la colonna. Se il valore è troppo alto, ad esempio il valore Sulfato superiore al 20%, potrebbe essere necessario applicare un controllo definito dall’utente che evidenzi questa colonna da escludere dall’uso futuro o da esaminare più attentamente.

Un metodo alternativo per verificare se sono presenti modelli di valori mancanti è applicare il metodo heatmap dalla libreria di visualizzazione dei dati seaborn.
# Visualizzare i valori mancanti utilizzando una heatmap per comprendere eventuali modelli
plt.figure(figsize=(15,8))
sns.heatmap(df.isnull());
Applicando il blocco di codice sopra, verrà prodotto l’output 1.10. Questa visualizzazione fornisce ulteriori informazioni per vedere se un numero di righe ha un valore mancante per tutte e tre le variabili. Potrebbe essere il caso che gli utenti che popolano i dati nell’insieme di dati originale mostrino costantemente valori mancanti. Avere questa conoscenza ci consentirebbe di produrre informazioni basate sui dati per individuare come ridurre in modo più efficiente il numero di valori mancanti.

Comprensione della distribuzione della variabile pH
Un’ultima valutazione sarebbe quella di eseguire una revisione di una variabile di cui abbiamo conoscenze esterne precedenti. Con la libreria seaborn, siamo in grado di produrre un istogramma della variabile pH.
# Impostazione dell'istogramma, della media e della mediana
sns.displot(df["ph"], kde=False)
plt.axvline(x=df.ph.mean(), linewidth=3, color='g', label="media", alpha=0.5)
plt.axvline(x=df.ph.median(), linewidth=3, color='y', label="mediana", alpha=0.5)
# Impostazione del titolo, delle legende e delle etichette
plt.xlabel("ph")
plt.ylabel("Conteggio")
plt.title("Distribuzione del pH", size=14)
plt.legend(["media", "mediana"]);
print(f'Valore medio del pH {df.ph.mean()} \n Valore mediano del pH {df.ph.median()} \n Valore minimo del pH {df.ph.min()} \n Valore massimo del pH {df.ph.max()}')
Come la dichiarazione di stampa precedente, la stringa f ci consente di aggiungere la media, la mediana, il minimo e il massimo per facilitare la revisione della distribuzione.

L’output 1.11 mostra che la maggior parte dei valori di pH è vicina al centro. Con una distribuzione simile a una distribuzione normale, potremmo utilizzare questa conoscenza per aiutare nella presentazione dei dettagli agli utenti esterni.
Conclusione
In tutto questo articolo, abbiamo cercato di esaminare le prime fasi di una valutazione EDA. All’inizio, sono state esaminate le metadati dei dati importati per visualizzare delle prime intuizioni. Un’analisi più approfondita delle statistiche di riepilogo ci ha permesso di concentrarci sui valori mancanti. Infine, abbiamo potuto esaminare l’istogramma della variabile pH per verificare che la variabile seguisse le aspettative esterne.
Un articolo successivo proseguirà il percorso e cercherà di sviluppare modelli che mirano a prevedere la qualità dell’acqua. Saranno utilizzate tecniche di apprendimento automatico di classificazione per fornire modelli di base.
Lascia i tuoi commenti e grazie mille per la lettura!
Puoi contattarmi su LinkedIn per una piacevole chiacchierata su tutto ciò che riguarda i dati. Altre storie che ho condiviso:
Dichiarazione di variabili in SQL
Assicurarsi che le variabili chiave siano dichiarate all’inizio del codice SQL può aiutare ad automatizzare il riutilizzo del codice.
towardsdatascience.com
Operazioni SQL avanzate
Revisione di operazioni SQL più avanzate per ottenere ulteriori insight dai dati meteorologici irlandesi.
towardsdatascience.com
Sviluppo di tabelle SQL
Creando e sviluppando tabelle SQL solo allora possiamo capire come sfruttare al meglio la memoria disponibile.
towardsdatascience.com
Iniziare con NLP in Python
Iniziare un viaggio nello spazio di Elaborazione del Linguaggio Naturale
towardsdatascience.com
[1]: Dataset Kaggle sulla qualità dell’acqua da https://www.kaggle.com/datasets/adityakadiwal/water-potability, con un accordo di licenza disponibile su https://creativecommons.org/publicdomain/zero/1.0/