🐼 Cos'è Pandas?
Pandas è la libreria Python più importante per la Data Science.
Fornisce strutture dati veloci, flessibili ed espressive progettate
per lavorare con dati "relazionali" o "etichettati" in modo intuitivo.
📊 Excel su Steroidi
Manipola milioni di righe come fossero un foglio Excel
🔧 Strumento Universale
Usato dal 90% dei data scientist worldwide
⚡ Performance
Scritto in C, veloce come linguaggi compilati
🏗️ Anatomia di Pandas
Series
DataFrame
Index
Columns
NaN Handling
GroupBy
Merge/Join
Pivot Tables
💡 Perché "Pandas"?
Il nome deriva da "Panel Data", non dall'orso!
È un gioco di parole che rappresenta dati tabellari multidimensionali.
📊 DataFrame: Il Cuore di Pandas
Un DataFrame è una tabella 2D (come un foglio Excel o una tabella SQL)
con righe e colonne etichettate. È la struttura dati più importante di Pandas.
1. Creazione di DataFrame
🚫 COPIA BLOCCATA
import pandas as pd
import numpy as np
# METODO 1: Da dizionario di liste (più comune)
dati_studenti = {
'Nome': ['Anna', 'Luca', 'Marco', 'Sofia', 'Giulia'],
'Età': [18, 19, 17, 18, 19],
'Voto_Matematica': [8.5, 7.0, 9.0, 6.5, 8.0],
'Voto_Italiano': [7.5, 8.0, 6.5, 9.0, 7.0],
'Classe': ['4A', '4B', '4A', '4B', '4A']
}
# Creazione DataFrame
df_studenti = pd.DataFrame(dati_studenti)
print("🎓 DATAFRAME STUDENTI")
print("=" * 50)
print(df_studenti)
print("\n📋 Informazioni DataFrame:")
print(f"Dimensioni: {df_studenti.shape}") # (righe, colonne)
print(f"Numero righe: {len(df_studenti)}")
print(f"Numero colonne: {df_studenti.shape[1]}")
print(f"Nomi colonne: {df_studenti.columns.tolist()}")
print(f"Indici: {df_studenti.index.tolist()}")
print(f"Tipi di dati:\n{df_studenti.dtypes}")
# METODO 2: Da lista di dizionari
dati_auto = [
{'Marca': 'Fiat', 'Modello': 'Panda', 'Anno': 2020, 'Prezzo': 15000},
{'Marca': 'Ford', 'Modello': 'Focus', 'Anno': 2019, 'Prezzo': 18000},
{'Marca': 'Toyota', 'Modello': 'Yaris', 'Anno': 2021, 'Prezzo': 20000},
]
df_auto = pd.DataFrame(dati_auto)
print("\n🚗 DATAFRAME AUTO")
print("=" * 50)
print(df_auto)
# METODO 3: Da array NumPy con indici e colonne personalizzati
dati_random = np.random.randn(4, 3) # 4 righe, 3 colonne di numeri casuali
df_random = pd.DataFrame(dati_random,
index=['Riga1', 'Riga2', 'Riga3', 'Riga4'],
columns=['ColA', 'ColB', 'ColC'])
print("\n🎲 DATAFRAME RANDOM")
print("=" * 50)
print(df_random)
📖 Costruttori DataFrame:
| Metodo |
Sintassi |
Quando usarlo |
| Da dizionario |
pd.DataFrame(dict) |
Dati già strutturati per colonne |
| Da lista di dict |
pd.DataFrame(list_of_dicts) |
Dati per righe (come JSON) |
| Da array NumPy |
pd.DataFrame(array, index=, columns=) |
Dati numerici, calcoli scientifici |
| Da CSV/Excel |
pd.read_csv(), pd.read_excel() |
Dati da file (più comune nella pratica) |
Attributi fondamentali DataFrame:
.shape: Tupla (righe, colonne)
.columns: Nomi colonne (Index object)
.index: Indici righe (Index object)
.dtypes: Tipi di dati per colonna
.info(): Informazioni complete
.describe(): Statistiche descrittive
2. Operazioni Base su DataFrame
🚫 COPIA BLOCCATA
# CONTINUA con df_studenti creato prima
print("🎯 OPERAZIONI BASE SU DATAFRAME")
print("=" * 50)
# 1. VISUALIZZAZIONE
print("\n1. 📊 VISUALIZZAZIONE:")
print("Prime 3 righe:")
print(df_studenti.head(3))
print("\nUltime 2 righe:")
print(df_studenti.tail(2))
print("\nCampione casuale (2 righe):")
print(df_studenti.sample(2, random_state=42))
# 2. SELEZIONE COLONNE
print("\n2. 🔍 SELEZIONE COLONNE:")
print("Colonna singola (restituisce Series):")
print(df_studenti['Nome'])
print("\nTipo:", type(df_studenti['Nome']))
print("\nColonne multiple (restituisce DataFrame):")
print(df_studenti[['Nome', 'Voto_Matematica']])
print("\nTipo:", type(df_studenti[['Nome', 'Voto_Matematica']]))
# 3. SELEZIONE RIGHE
print("\n3. 📝 SELEZIONE RIGHE:")
print("Per indice (numerico):")
print(df_studenti.iloc[0]) # Prima riga
print("\nPer etichetta (se abbiamo indici non numerici):")
print(df_studenti.loc[0]) # Stessa cosa se indice è 0,1,2,...
# 4. SELEZIONE CELLE SPECIFICHE
print("\n4. 📍 SELEZIONE CELLE SPECIFICHE:")
print("Valore specifico (iloc):")
print(f"Studente indice 2, colonna 'Nome': {df_studenti.iloc[2, 0]}")
print(f"Studente indice 1, colonna 3: {df_studenti.iloc[1, 3]}")
print("\nValore specifico (loc):")
print(f"Studente indice 3, colonna 'Voto_Matematica': {df_studenti.loc[3, 'Voto_Matematica']}")
# 5. FILTRI BOOLEANI (IMPORTANTISSIMI!)
print("\n5. 🎯 FILTRI BOOLEANI:")
print("Studenti con voto matematica > 8:")
voti_alto = df_studenti[df_studenti['Voto_Matematica'] > 8]
print(voti_alto)
print("\nStudenti di classe 4A:")
classe_4a = df_studenti[df_studenti['Classe'] == '4A']
print(classe_4a)
print("\nStudenti con voto italiano tra 7 e 8:")
voti_medio = df_studenti[(df_studenti['Voto_Italiano'] >= 7) &
(df_studenti['Voto_Italiano'] <= 8)]
print(voti_medio)
print("\nStudenti di 19 anni OPPURE voto matematica > 7.5:")
condizione_complessa = df_studenti[(df_studenti['Età'] == 19) |
(df_studenti['Voto_Matematica'] > 7.5)]
print(condizione_complessa)
# 6. OPERAZIONI STATISTICHE
print("\n6. 📈 OPERAZIONI STATISTICHE:")
print("Statistiche descrittive:")
print(df_studenti.describe())
print("\nStatistiche per colonna specifica:")
print(f"Media voto matematica: {df_studenti['Voto_Matematica'].mean():.2f}")
print(f"Mediana voto italiano: {df_studenti['Voto_Italiano'].median():.2f}")
print(f"Voto massimo matematica: {df_studenti['Voto_Matematica'].max()}")
print(f"Voto minimo italiano: {df_studenti['Voto_Italiano'].min()}")
print(f"Deviazione standard età: {df_studenti['Età'].std():.2f}")
# 7. MODIFICA DATAFRAME
print("\n7. ✏️ MODIFICA DATAFRAME:")
# Aggiunta nuova colonna
df_studenti['Voto_Media'] = (df_studenti['Voto_Matematica'] +
df_studenti['Voto_Italiano']) / 2
print("Con colonna media voti:")
print(df_studenti)
# Modifica valori esistenti
df_studenti.loc[0, 'Voto_Matematica'] = 9.0 # Anna prende 9 in matematica
print("\nDopo modifica voto di Anna:")
print(df_studenti)
# Rimozione colonna
# df_studenti = df_studenti.drop('Voto_Media', axis=1) # Per rimuoverla
# 8. ORDINAMENTO
print("\n8. 🔼 ORDINAMENTO:")
print("Ordinato per voto matematica (decrescente):")
print(df_studenti.sort_values('Voto_Matematica', ascending=False))
print("\nOrdinato per classe (crescente) e poi per nome (crescente):")
print(df_studenti.sort_values(['Classe', 'Nome']))
# 9. OPERAZIONI DI GRUPPO (GROUPBY)
print("\n9. 👥 OPERAZIONI DI GRUPPO:")
print("Media voti per classe:")
gruppo_classe = df_studenti.groupby('Classe')
print(gruppo_classe[['Voto_Matematica', 'Voto_Italiano', 'Voto_Media']].mean())
print("\nNumero studenti per classe:")
print(df_studenti['Classe'].value_counts())
📖 Differenza tra iloc e loc:
| Metodo |
Seleziona per... |
Esempio |
Restituisce |
.iloc[] |
Posizione numerica |
df.iloc[0, 1] |
Prima riga, seconda colonna |
.loc[] |
Etichetta/indice |
df.loc[0, 'Nome'] |
Riga con indice 0, colonna 'Nome' |
Operatori logici nei filtri:
&: AND (entrambe le condizioni devono essere vere)
|: OR (almeno una condizione deve essere vera)
~: NOT (negazione)
- Importante: Usare parentesi attorno a ogni condizione!
Metodi chiave di DataFrame:
.head(n): Prime n righe
.tail(n): Ultime n righe
.sample(n): n righe casuali
.sort_values(): Ordina per colonna
.groupby(): Raggruppa per valori
.value_counts(): Conta valori unici
🎯 ESERCITAZIONE GUIDATA: Analisi Dati Meteo
📖 Scenario
Sei un data scientist che lavora per un'azienda di turismo. Ti hanno fornito i dati meteo di una settimana e devi:
- Creare un DataFrame con i dati
- Calcolare statistiche utili
- Trovare i giorni migliori per attività all'aperto
- Generare un report sintetico
📊 Dati di Partenza
🚫 COPIA BLOCCATA
# DATI METEO SETTIMANALI
dati_meteo = {
'Giorno': ['Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato', 'Domenica'],
'Temperatura_C': [22, 24, 19, 25, 23, 20, 18],
'Umidita_%': [65, 70, 80, 60, 75, 85, 90],
'Precipitazioni_mm': [0, 2.5, 10.0, 0, 1.0, 15.0, 20.0],
'Vento_kmh': [15, 10, 25, 12, 18, 30, 35]
}
# 1. CREA IL DATAFRAME
df_meteo = pd.DataFrame(dati_meteo)
print("🌤️ DATI METEO SETTIMANALI")
print("=" * 50)
print(df_meteo)
print("\n" + "="*50)
# 2. AGGIUNGI NUOVE COLONNE UTILI
# Converti temperatura in Fahrenheit: F = C × 9/5 + 32
df_meteo['Temperatura_F'] = df_meteo['Temperatura_C'] * 9/5 + 32
# Aggiungi colonna "Giornata_Bella" (temp > 20 e pioggia < 5mm e vento < 20 km/h)
df_meteo['Giornata_Bella'] = (df_meteo['Temperatura_C'] > 20) & \
(df_meteo['Precipitazioni_mm'] < 5) & \
(df_meteo['Vento_kmh'] < 20)
print("\n📈 DATAFRAME AGGIORNATO:")
print(df_meteo)
# 3. ANALISI STATISTICHE
print("\n" + "="*50)
print("📊 ANALISI STATISTICHE")
print("=" * 50)
print(f"\n🌡️ TEMPERATURA:")
print(f"Media: {df_meteo['Temperatura_C'].mean():.1f}°C")
print(f"Massima: {df_meteo['Temperatura_C'].max()}°C ({df_meteo.loc[df_meteo['Temperatura_C'].idxmax(), 'Giorno']})")
print(f"Minima: {df_meteo['Temperatura_C'].min()}°C ({df_meteo.loc[df_meteo['Temperatura_C'].idxmin(), 'Giorno']})")
print(f"\n💧 PRECIPITAZIONI:")
print(f"Totale settimana: {df_meteo['Precipitazioni_mm'].sum():.1f} mm")
print(f"Media giornaliera: {df_meteo['Precipitazioni_mm'].mean():.1f} mm")
print(f"Giorni con pioggia (>0 mm): {len(df_meteo[df_meteo['Precipitazioni_mm'] > 0])}")
print(f"\n💨 VENTO:")
print(f"Velocità media: {df_meteo['Vento_kmh'].mean():.1f} km/h")
print(f"Giorno più ventoso: {df_meteo.loc[df_meteo['Vento_kmh'].idxmax(), 'Giorno']} ({df_meteo['Vento_kmh'].max()} km/h)")
# 4. SELEZIONA LE GIORNATE MIGLIORI
print("\n" + "="*50)
print("🌟 GIORNATE MIGLIORI PER ATTIVITÀ ALL'APERTO")
print("=" * 50)
giorni_belli = df_meteo[df_meteo['Giornata_Bella'] == True]
print(f"\nGiornate belle totali: {len(giorni_belli)}")
print("\nLista giornate belle:")
print(giorni_belli[['Giorno', 'Temperatura_C', 'Precipitazioni_mm', 'Vento_kmh']])
# 5. RAGGRUPPAMENTO PER TIPOLOGIA DI GIORNO
print("\n" + "="*50)
print("📋 CLASSIFICAZIONE GIORNI")
print("=" * 50)
# Aggiungi classificazione
def classifica_giorno(temp, pioggia, vento):
if pioggia > 10:
return 'Piovoso'
elif vento > 25:
return 'Ventoso'
elif temp > 23:
return 'Caldo'
elif temp < 20:
return 'Fresco'
else:
return 'Perfetto'
df_meteo['Tipo_Giorno'] = df_meteo.apply(
lambda row: classifica_giorno(row['Temperatura_C'],
row['Precipitazioni_mm'],
row['Vento_kmh']),
axis=1
)
print("\n📊 GIORNI PER CATEGORIA:")
print(df_meteo['Tipo_Giorno'].value_counts())
print("\n📝 REPORT COMPLETO:")
for tipo in df_meteo['Tipo_Giorno'].unique():
giorni = df_meteo[df_meteo['Tipo_Giorno'] == tipo]['Giorno'].tolist()
print(f"\n{tipo}: {', '.join(giorni)}")
# 6. SALVA I RISULTATI
print("\n" + "="*50)
print("💾 SALVATAGGIO RISULTATI")
print("=" * 50)
# Salva su CSV
df_meteo.to_csv('analisi_meteo_settimana.csv', index=False)
print("✅ Dati salvati in 'analisi_meteo_settimana.csv'")
# Salva solo giornate belle
giorni_belli.to_csv('giornate_belle_settimana.csv', index=False)
print("✅ Giornate belle salvate in 'giornate_belle_settimana.csv'")
print("\n🎉 ANALISI COMPLETATA CON SUCCESSO!")
🎯 Cosa hai imparato in questa esercitazione:
- Creazione DataFrame da dizionario
- Aggiunta nuove colonne con calcoli
- Filtri complessi con condizioni multiple
- Statistiche descrittive avanzate
- Funzioni personalizzate con apply()
- Salvataggio dati in CSV
Trucco professionale: La funzione apply() permette di applicare qualsiasi funzione Python a ogni riga/colonna del DataFrame. È potentissima!
📁 Lettura Dati da File
Nella pratica, i dati arrivano da file. Pandas supporta decine di formati!
🚫 COPIA BLOCCATA
import pandas as pd
print("📚 LETTURA DATI DA VARI FORMATI")
print("=" * 50)
# 1. CSV (Comma Separated Values) - IL PIÙ COMUNE
print("\n1. 📄 LETTURA CSV:")
# Sintassi base
# df = pd.read_csv('percorso/file.csv')
# Parametri utili per CSV:
# df = pd.read_csv('file.csv',
# sep=',', # separatore (può essere ';', '\t', ecc)
# header=0, # riga da usare come intestazione
# index_col=0, # colonna da usare come indice
# encoding='utf-8', # codifica caratteri
# na_values=['NA', 'null', '']) # valori da considerare NaN
# Esempio pratico (per Google Colab):
# from google.colab import files
# uploaded = files.upload() # Carica il file
# df = pd.read_csv('nome_file.csv')
# 2. EXCEL
print("\n2. 📊 LETTURA EXCEL:")
# df_excel = pd.read_excel('file.xlsx',
# sheet_name='Foglio1', # nome foglio
# header=0,
# engine='openpyxl') # motore per leggere .xlsx
# Per leggere fogli multipli:
# excel_file = pd.ExcelFile('file.xlsx')
# df_foglio1 = pd.read_excel(excel_file, 'Foglio1')
# df_foglio2 = pd.read_excel(excel_file, 'Foglio2')
# 3. JSON
print("\n3. 🗂️ LETTURA JSON:")
# df_json = pd.read_json('file.json')
# df_json = pd.read_json('file.json', orient='records') # formato più comune
# 4. DATABASE SQL
print("\n4. 🗃️ LETTURA DA DATABASE SQL:")
import sqlite3 # Esempio con SQLite
# Crea connessione
# conn = sqlite3.connect('database.db')
# query = "SELECT * FROM tabella WHERE condizione"
# df_sql = pd.read_sql(query, conn)
# conn.close()
print("\n🎯 ESEMPIO COMPLETO: Lettura e analisi CSV")
# Simuliamo un file CSV
csv_content = """Nome,Età,Città,Stipendio
Mario Rossi,30,Roma,35000
Luigi Verdi,25,Milano,42000
Anna Bianchi,35,Napoli,38000
Giovanni Neri,28,Torino,45000
Maria Russo,40,Bologna,39000"""
# Salva come file temporaneo (per simulazione)
with open('dipendenti.csv', 'w', encoding='utf-8') as f:
f.write(csv_content)
# Leggi il file CSV
df_dipendenti = pd.read_csv('dipendenti.csv')
print("\n📋 DATI DIPENDENTI (da CSV):")
print(df_dipendenti)
print("\n📊 INFORMAZIONI:")
print(df_dipendenti.info())
print("\n📈 STATISTICHE:")
print(df_dipendenti.describe())
# Analisi avanzata
print("\n🔍 ANALISI AVANZATA:")
print(f"Numero dipendenti: {len(df_dipendenti)}")
print(f"Età media: {df_dipendenti['Età'].mean():.1f} anni")
print(f"Stipendio medio: €{df_dipendenti['Stipendio'].mean():,.0f}")
print(f"\nDipendenti per città:")
print(df_dipendenti['Città'].value_counts())
# Filtri avanzati
print("\n🎯 DIPENDENTI CON STIPENDIO > 40000:")
print(df_dipendenti[df_dipendenti['Stipendio'] > 40000])
print("\n👵 DIPENDENTI OVER 35:")
print(df_dipendenti[df_dipendenti['Età'] > 35])
# Salva risultati in nuovo CSV
df_dipendenti.to_csv('analisi_dipendenti.csv', index=False)
print("\n💾 Dati analizzati salvati in 'analisi_dipendenti.csv'")
# Pulizia file temporaneo
import os
os.remove('dipendenti.csv')
print("🧹 File temporaneo rimosso")
📖 Formati supportati da Pandas:
| Formato |
Funzione lettura |
Funzione scrittura |
Quando usarlo |
| CSV/TSV |
read_csv() |
to_csv() |
Scambio dati universale |
| Excel |
read_excel() |
to_excel() |
Report aziendali |
| JSON |
read_json() |
to_json() |
API web, configurazioni |
| SQL |
read_sql() |
to_sql() |
Database aziendali |
| Parquet |
read_parquet() |
to_parquet() |
Big data, performance |
| HTML |
read_html() |
to_html() |
Web scraping |
🎓 Riepilogo del Modulo
✅ Pandas Series: Array 1D etichettato, cuore della libreria
✅ DataFrame: Tabella 2D, struttura dati principale
✅ Creazione: Da dizionari, liste, array NumPy
✅ Selezione dati: loc[], iloc[], filtri booleani
✅ Operazioni: Statistiche, ordinamento, groupby
✅ Lettura/scrittura: CSV, Excel, JSON, SQL
✅ Manipolazione: Aggiunta/rimozione colonne, modifiche
✅ Analisi reale: Esercitazione guidata completa
💡 Pro Tip per Google Colab
Per caricare file su Colab, usa:
🚫 COPIA BLOCCATA
from google.colab import files
uploaded = files.upload() # Scegli il file dal tuo computer
df = pd.read_csv(next(iter(uploaded))) # Leggi il primo file caricato
🚀 Pronto per il prossimo livello?
Nel Modulo 2 affronteremo:
- 🎯 Data Cleaning avanzato
- 🔗 Merge & Join di DataFrame multipli
- 📊 Pivot Tables e analisi multidimensionale
- ⏱️ Time Series con datetime
- 🐼 Pandas avanzato: apply(), lambda, ottimizzazioni
Vai al Modulo 2 →