Leggere un CSV e controllare cosa è arrivato
Leggere un file con read_csv e ispezionarlo subito con shape, head, info e describe — perché un file letto male restituisce risposte errate senza mai generare errori.
Come vuoi imparare?
Il problema che stiamo risolvendo
Finora ogni valore nella tabella è stato inserito a mano nel codice. Con tre righe, funziona.
I dati reali non vivono nel codice. Vivono in un file — inviato via email da qualcuno, esportato da un sistema o salvato da un foglio di calcolo. E il file ha dodicimila righe, non dodici.
Quel file di solito si presenta così: testo semplice, i nomi delle colonne sulla prima riga, poi una riga di dati per ogni riga del file, con i valori separati da virgole:
product,quantity,price
pen,12,15.0
notebook,5,60.0Questo è un CSV — comma-separated values. Trasformarlo in una tabella richiede una sola riga di pandas, ed è la singola riga più usata in pandas.
Ma c'è un'abitudine da sviluppare subito dopo quella riga, ed è il vero tema di questo capitolo: una volta letto un file, guardalo. Quante righe sono arrivate, se i nomi delle colonne sono quelli attesi, se le colonne numeriche sono state importate davvero come numeri. Salta quei trenta secondi e l'errore emergerà molto più tardi, quando un risultato sarà sbagliato e nessun errore sarà stato segnalato.
Alla fine di questo capitolo sarai in grado di
- Leggere un file con
pd.read_csv()e gestire il problema del percorso che ne consegue - Controllare rapidamente un file con
head(),tail(),shapeecolumns - Leggere
info()per vedere contemporaneamente il conteggio delle righe, le celle vuote e il tipo di ogni colonna - Riassumere le colonne numeriche con
describe() - Riconoscere e risolvere un
FileNotFoundErrore il problema del separatore errato
Prerequisiti: Series e DataFrame — le due strutture di pandas.
Crea prima il file
Nella cartella del tuo progetto, crea un file chiamato sales.csv con esattamente queste sei righe:
product,quantity,price
pen,12,15.0
notebook,5,60.0
bag,2,850.0
bottle,7,120.0
eraser,30,8.0La prima riga non contiene dati, ma i nomi delle colonne — l'intestazione. Le altre cinque righe sono cinque righe di dati.
Leggerlo, in una sola riga
import pandas as pd
sales = pd.read_csv("sales.csv")
print(sales)product quantity price
0 pen 12 15.0
1 notebook 5 60.0
2 bag 2 850.0
3 bottle 7 120.0
4 eraser 30 8.0Quella singola riga ha fatto tre cose, e tutte e tre in silenzio:
Primo, ha preso la prima riga come intestazione — così product, quantity e price sono diventati nomi di colonna anziché una riga.
Secondo, ha costruito un indice, da 0 a 4 lungo il lato sinistro. Nel file non c'era.
Terzo, e questo è l'aspetto fondamentale, ha indovinato il tipo di ogni colonna. Nel file tutto è testo — 12 in realtà sono due caratteri. Pandas ha esaminato ciascuna colonna e ha deciso se si trattasse di numeri o di testo.
L'ipotesi di solito è corretta. Ma quando è sbagliata, non viene generato alcun errore — ed è esattamente per questo che devi controllare.
Le quattro cose da controllare dopo aver letto un file
shape — quanto è arrivato
print(sales.shape)(5, 3)Cinque righe, tre colonne. Il file conteneva sei righe e questo ne ha cinque, perché l'intestazione non è una riga. Se il numero è molto inferiore a quello previsto, o esattamente di uno in più, è il primo segno che qualcosa è stato letto in modo errato.
head() e tail() — l'inizio e la fine
print(sales.head(3))product quantity price
0 pen 12 15.0
1 notebook 5 60.0
2 bag 2 850.0Stampare tutte le dodicimila righe di un file reale riempie il terminale e non ti dice nulla. head() mostra le prime — cinque se non specifichi diversamente. tail() fa lo stesso alla fine, ed esaminare la fine è altrettanto utile, perché i file esportati spesso contengono laggiù una riga vuota spuria o una riga con i totali.
info() — tutto a colpo d'occhio
sales.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 product 5 non-null object
1 quantity 5 non-null int64
2 price 5 non-null float64
dtypes: float64(1), int64(1), object(1)
memory usage: 252.0+ bytesNota che è scritto sales.info() e non print(sales.info()) — questo metodo stampa da solo e non restituisce nulla, quindi avvolgerlo in print aggiunge un None spurio alla fine.
Questa è la cosa più utile da eseguire dopo aver letto un file, perché fornisce due informazioni importanti contemporaneamente:
Non-Null Count — quante celle in ciascuna colonna sono effettivamente piene. Qui tutte e tre indicano 5 non-null, quindi nessuna è vuota. Un eventuale 4 non-null significa che una cella in quella colonna è vuota, e questo cambierà i tuoi calcoli.
Dtype — il tipo stabilito dall'inferenza automatica. quantity è stata importata come int64, price come float64, product come object. È esattamente ciò che volevamo.
(Il valore di memory usage sull'ultima riga potrebbe differire sul tuo computer, e non ha importanza.)
describe() — un riepilogo delle colonne numeriche
print(sales.describe())quantity price
count 5.00000 5.000000
mean 11.20000 210.600000
std 11.12205 360.217712
min 2.00000 8.000000
25% 5.00000 15.000000
50% 7.00000 60.000000
75% 12.00000 120.000000
max 30.00000 850.000000Seleziona le colonne numeriche ed esegue otto calcoli su ciascuna. product è assente, perché è testo.
Qui una cosa dovrebbe attirare la tua attenzione: il valore di mean per price è 210.6, mentre il 50% — la mediana — è solo 60. Una differenza così ampia significa che un valore si trova molto al di sopra del resto, e max lo indica esplicitamente: 850. È così che si legge describe() — quando la media e la mediana divergono, guarda lì.
Un esempio completo
report.py:
import pandas as pd
sales = pd.read_csv("sales.csv")
print("Rows, columns:", sales.shape)
print()
print(sales.head(3))
print()
print("Columns :", list(sales.columns))
print("Total qty :", sales["quantity"].sum())
print("Avg price :", round(sales["price"].mean(), 2))Rows, columns: (5, 3)
product quantity price
0 pen 12 15.0
1 notebook 5 60.0
2 bag 2 850.0
Columns : ['product', 'quantity', 'price']
Total qty : 56
Avg price : 210.6Un piccolo programma, ma la sua struttura merita attenzione — leggi, poi controlla, poi calcola. shape e head() non sono calcoli, sono domande: ho letto il file corretto? Ci sono tante righe quante dovrebbero essercene?
E c'è un motivo per stampare list(sales.columns). Sotto forma di lista, ogni nome viene restituito tra virgolette, quindi un nome come 'quantity ' con uno spazio finale è immediatamente visibile. Stampato in qualsiasi altro modo, quello spazio rimane invisibile e si ripresenta più tardi come un KeyError.
Quando qualcosa va storto
FileNotFoundError: [Errno 2] No such file or directory: 'sales.csv' Python cerca nella cartella corrente e non lo trova lì. È lo stesso problema del capitolo due del corso di Python: il terminale si trova in un posto e il file in un altro. Esegui pwd per vedere dove ti trovi, dir per verificare se il file è lì, poi cd. Su Windows il nome potrebbe in realtà essere sales.csv.txt — attiva le estensioni dei nomi dei file in Esplora file.
L'intero file è arrivato come una singola colonna Il separatore non è una virgola. I file salvati in gran parte d'Europa usano il punto e virgola, perché lì la virgola è il separatore decimale. Scrivi pd.read_csv("sales.csv", sep=";"). Per i file separati da tabulazioni, sep="\t".
Una colonna numerica è stata importata come object Del testo è finito da qualche parte nella colonna — un N/A, un -, una cella vuota o una virgola per le migliaia (1,200). Esegui df["col"].unique() per vedere cosa c'è davvero dentro; il valore anomalo di solito risalta subito. La correzione è pd.to_numeric(df["col"], errors="coerce"), che trasforma qualsiasi cosa non numerica in un valore vuoto — argomento trattato approfonditamente nel capitolo sui dati mancanti.
UnicodeDecodeError Il file non è salvato come UTF-8, cosa che accade abitualmente con i file generati da un foglio di calcolo. Prova con pd.read_csv("sales.csv", encoding="utf-8-sig"), e se non funziona usa encoding="latin-1".
La prima riga di dati è diventata i nomi delle colonne, anche se il file non aveva un'intestazione Scrivi pd.read_csv("sales.csv", header=None) e le colonne diventeranno 0, 1, 2. Per assegnare loro un nome, aggiungi names=["product", "quantity", "price"].
Un None spurio è stato stampato dopo sales.info() È stato scritto come print(sales.info()). info() stampa da solo e non restituisce nulla, quindi print stampa il None restituito. Scrivi semplicemente sales.info().
Passo 4 di 6 — Prevedi
Verifica cosa hai capito
Il file ha sei righe. Cosa indica shape?
from io import StringIO
import pandas as pd
# Stands in for sales.csv, so this snippet runs on its own.
RAW = """product,quantity,price
pen,12,15.0
notebook,5,60.0
bag,2,850.0
bottle,7,120.0
eraser,30,8.0
"""
sales = pd.read_csv(StringIO(RAW))
print(sales.shape)- A(5, 3)
- B(5, 4)
- C(3, 5)
- D(6, 3)
Cosa ti dice la colonna Non-Null Count di info()?
- AQuante celle in ciascuna colonna sono effettivamente piene — un numero inferiore al conteggio delle righe indica la presenza di valori vuoti
- BQuante celle in ciascuna colonna sono vuote
- CQuanto spazio occupa ciascuna colonna
- DQuanti valori distinti ha ciascuna colonna
Il file è separato da punti e virgola, ma non è stato specificato sep. Cosa viene stampato?
from io import StringIO
import pandas as pd
# Stands in for sales.csv, so this snippet runs on its own.
RAW = """product;quantity
pen;12
notebook;5
"""
df = pd.read_csv(StringIO(RAW))
print(df.shape)
print(list(df.columns))- A(3, 1) ['product;quantity']
- B(2, 1) ['product;quantity']
- C(2, 2) ['product', 'quantity']
- DUn `ParserError`
Per rispondere serve un account
Accedi per verificare le tue risposte
Le domande sono qui sopra, e ragionarci a mente è la parte che conta. Accedi per vedere le risposte, le spiegazioni e i suggerimenti a tre livelli.
Tocca a te
Crea un file chiamato students.csv contenente almeno otto persone, in tre colonne — un nome, un'età e un voto.
Poi scrivi report.py, che:
- Legge il file
- Stampa
shapeelist(columns) - Stampa
head(3)etail(2) - Esegue
info()e indica se i tipi di tutte e tre le colonne sono quelli previsti - Stampa
describe(), e separatamente la media e il massimo della colonna dei voti
Poi rompilo di proposito — per tre volte, notando cosa succede ogni volta:
- Inserisci
N/Ain una cella della colonna dei voti. Cosa indicaDtypeininfo()adesso? Cosa è successo alla media? - Sostituisci ogni virgola nel file con un punto e virgola. Cosa indica
shapeadesso, e perché? - Elimina la prima riga, l'intestazione. Quante righe sono arrivate, e quali sono i nomi delle colonne adesso?
Tutti e tre i casi si verificano abitualmente nel lavoro reale, e ciascuno presenta un sintomo chiaro. Provocarli deliberatamente oggi ti permetterà di riconoscerli al primo sguardo la prossima volta.
Passo 6 di 6
Sfida — il quiz del capitolo
Dieci domande dalla più facile alla più difficile. Le ultime sono difficili di proposito.
Accedi per fare il quiz