Join sinistri e destri
Esegua join sinistri e destri per conservare tutte le righe di una tabella abbinandole ai record dell'altra.
Join sinistri e destri è una lezione Pandas & NumPy Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Pandas & NumPy Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Pandas & NumPy Academy include 4 lezioni in totale.
Join asimmetrici
I join interni ed esterni trattano entrambi i DataFrame in modo simmetrico. Spesso, però, si desidera conservare tutti i record di una tabella e arricchirli con i dati di un'altra. È qui che entrano in gioco i join sinistri e i join destri. Questi join asimmetrici sono molto comuni nell'analisi dei dati: conservare tutte le transazioni e aggiungere i nomi dei prodotti quando disponibili; conservare tutti gli utenti e aggiungere la data dell'ultimo acquisto, se presente.
Join sinistro: conservare tutte le righe a sinistra
Un join sinistro (how='left') conserva ogni riga del DataFrame a sinistra. Per le righe che trovano una chiave corrispondente nel DataFrame a destra, le colonne di destra vengono valorizzate con i valori corrispondenti. Per le righe senza corrispondenza, le colonne di destra vengono valorizzate con NaN. Il numero di righe del risultato è sempre uguale a quello del DataFrame a sinistra, purché non vi siano chiavi duplicate.
import pandas as pd
orders = pd.DataFrame({
'order_id': [1, 2, 3, 4],
'customer_id': [101, 102, 101, 999],
'amount': [250, 80, 320, 150]
})
customers = pd.DataFrame({
'customer_id': [101, 102, 103],
'name': ['Alice', 'Bob', 'Carol']
})
result = pd.merge(orders, customers, on='customer_id', how='left')
print(result)
# All 4 orders kept; order with customer_id=999 gets NaN for nameStruttura del risultato di un join sinistro
Dopo un join sinistro, le righe del DataFrame a sinistra che non hanno trovato una corrispondenza nel DataFrame a destra avranno NaN in ogni colonna proveniente dalla tabella a destra. Può usare questa caratteristica per identificare le righe non corrispondenti con un filtro booleano su una colonna della tabella a destra e per contare quante righe a sinistra non hanno trovato corrispondenza: un utile controllo della qualità dei dati.
result = pd.merge(orders, customers, on='customer_id', how='left')
print(result)
# order_id customer_id amount name
# 0 1 101 250 Alice
# 1 2 102 80 Bob
# 2 3 101 320 Alice
# 3 4 999 150 NaN <- no matching customer
# Count unmatched
unmatched = result['name'].isna().sum()
print(f'{unmatched} orders have no customer record')Quando usare un join sinistro
I join sinistri sono appropriati quando il DataFrame a sinistra è la tabella principale e quello a destra è complementare. Alcuni casi comuni sono: arricchire una tabella dei fatti con una tabella delle dimensioni (ordini + nomi dei prodotti), aggiungere metadati facoltativi (utenti + dati del profilo) oppure calcolare metriche per tutti i record anche quando una ricerca non ha esito. Nella maggior parte del codice di analisi, i join sinistri sono molto più comuni dei join destri.
# Realistic pattern: enrich all products with optional category data
products = pd.DataFrame({'sku': ['A1', 'B2', 'C3'], 'price': [10, 20, 15]})
categories = pd.DataFrame({'sku': ['A1', 'C3'], 'category': ['Tools', 'Home']})
# Keep all products; add category where available
enriched = pd.merge(products, categories, on='sku', how='left')
print(enriched)
# sku price category
# 0 A1 10 Tools
# 1 B2 20 NaN
# 2 C3 15 HomeJoin destro: conservare tutte le righe a destra
Un join destro (how='right') è l'immagine speculare di un join sinistro: conserva ogni riga del DataFrame a destra e inserisce NaN nelle colonne della tabella a sinistra quando non esiste una corrispondenza. Un join destro è meno comune, perché è sempre possibile ottenere lo stesso risultato invertendo gli argomenti dei DataFrame e usando invece un join sinistro, più chiaro per chi legge il codice.
# Right join: keep all customers, attach orders where they exist
result = pd.merge(orders, customers, on='customer_id', how='right')
print(result)
# All 3 customers appear; Carol (103) has NaN for order_id and amount
# Equivalent left join (swap arguments):
result2 = pd.merge(customers, orders, on='customer_id', how='left')
# Same data, just column order differsConfrontare tutti e quattro i tipi di join
I quattro tipi di join differiscono solo per le righe del lato senza corrispondenze che vengono conservate. inner: solo le righe corrispondenti. outer: tutte le righe di entrambi i lati. left: tutte le righe a sinistra. right: tutte le righe a destra. Per le voci senza corrispondenza, le colonne del lato assente vengono valorizzate con NaN. Scegliere correttamente è fondamentale per evitare di eliminare o duplicare record senza accorgersene.
# Summary table
# how='inner' : rows in BOTH tables
# how='left' : ALL left rows + matched right
# how='right' : matched left + ALL right rows
# how='outer' : ALL left rows + ALL right rows
# Test each
for how in ['inner', 'left', 'right', 'outer']:
r = pd.merge(orders, customers, on='customer_id', how=how)
print(f'{how}: {len(r)} rows')Valorizzare NaN nei risultati di un join sinistro
Dopo un join sinistro, le righe senza corrispondenza contengono NaN nelle colonne della tabella a destra. Spesso è utile sostituire questi valori con impostazioni predefinite appropriate, ad esempio 'Unknown' per una categoria mancante o 0 per un conteggio mancante. Usi fillna() sul risultato oppure passi fill_value nelle operazioni aritmetiche successive al join.
result = pd.merge(products, categories, on='sku', how='left')
result['category'] = result['category'].fillna('Uncategorised')
print(result)
# sku price category
# 0 A1 10 Tools
# 1 B2 20 Uncategorised
# 2 C3 15 HomeAnti-join sinistro: righe senza corrispondenza
Un modello utile non supportato direttamente da how è l'anti-join: conservare solo le righe a sinistra che NON hanno corrispondenze nella tabella a destra. Lo si implementa con un join sinistro usando indicator=True, quindi filtrando per _merge == 'left_only'. È perfetto per trovare record orfani, nuovi elementi non presenti in un elenco di riferimento o transazioni mancanti in un registro contabile.
# Anti-join: orders with no matching customer record
result = pd.merge(orders, customers, on='customer_id',
how='left', indicator=True)
unmatched_orders = result[result['_merge'] == 'left_only'].drop(columns='_merge')
print(unmatched_orders)
# order_id customer_id amount name
# 3 4 999 150 NaNPreservare il numero di righe con un join sinistro
Quando il DataFrame a destra ha chiavi univoche, un join sinistro garantisce la conservazione esatta del numero di righe della tabella a sinistra. Tuttavia, se la tabella a destra contiene valori duplicati nella chiave, il join sinistro moltiplica le righe proprio come un join interno. Verifichi sempre che il numero di righe in output corrisponda a quello della tabella a sinistra quando si aspetta una relazione uno-a-molti.
# Right table has duplicate keys -> row multiplication
orders_small = pd.DataFrame({'id': [1, 2], 'amount': [100, 200]})
multi_customer = pd.DataFrame({
'id': [1, 1], # duplicate!
'contact': ['Alice', 'Alice2']
})
result = pd.merge(orders_small, multi_customer, on='id', how='left')
print(len(result)) # 3 rows! order 1 appears twice
print(result)Modello di join sinistro nel mondo reale
Ecco un flusso di lavoro completo e realistico: inizi con un registro delle transazioni, esegua un join sinistro con un catalogo dei prodotti per ottenere i nomi, quindi esegua un altro join sinistro con una tabella dei clienti per ottenere i nomi. Sostituisca le ricerche senza risultato con valori predefiniti. La catena di join sinistri garantisce che ogni riga delle transazioni venga conservata, anche se il prodotto o il cliente manca nelle tabelle di riferimento.
transactions = pd.DataFrame({
'txn_id': [1, 2, 3],
'cust_id': [10, 11, 99],
'prod_id': [20, 21, 20],
'total': [50, 30, 70]
})
custs = pd.DataFrame({'cust_id': [10, 11], 'cust_name': ['Alice', 'Bob']})
prods = pd.DataFrame({'prod_id': [20, 21], 'prod_name': ['Widget', 'Gadget']})
result = (
transactions
.merge(custs, on='cust_id', how='left')
.merge(prods, on='prod_id', how='left')
)
print(result)Scegliere tra join sinistro e join interno
La scelta tra join sinistro e join interno è una decisione di logica aziendale: si devono conservare i record senza una corrispondenza nella ricerca oppure eliminarli senza avviso? Usi un join sinistro quando le ricerche senza risultato sono accettabili e desidera conservare tutti i record principali. Usi un join interno quando una ricerca senza risultato indica che il record non è valido e deve essere escluso dall'analisi. Documenti sempre la scelta effettuata e la relativa motivazione.
# Left join: keep all transactions (some may have no product name)
result_left = pd.merge(transactions, prods, on='prod_id', how='left')
print('Left join rows:', len(result_left)) # same as transactions
# Inner join: only transactions with known product
result_inner = pd.merge(transactions, prods, on='prod_id', how='inner')
print('Inner join rows:', len(result_inner)) # may be fewerVerifica rapida
Verifichi la sua comprensione dei join sinistri e destri presentati in questa lezione.
Riepilogo della lezione
In questa lezione ha imparato che il join sinistro conserva tutte le righe del DataFrame a sinistra, valorizzando con NaN le colonne di destra per le righe senza corrispondenza; il join destro è l'immagine speculare; il modello di anti-join con indicator=True trova le righe a sinistra senza corrispondenza a destra; infine, la scelta tra join sinistro e interno è una decisione di logica aziendale. Ora esploreremo l'unione dei DataFrame tramite il loro indice anziché una colonna.
Domande Frequenti
La lezione «Join sinistri e destri» è gratuita?
Sì — il testo completo di «Join sinistri e destri» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Pandas & NumPy Academy, passa a CoddyKit PRO. Il corso Pandas & NumPy Academy include 4 lezioni in totale.
Cosa imparerò in «Join sinistri e destri»?
Esegua join sinistri e destri per conservare tutte le righe di una tabella abbinandole ai record dell'altra. Eserciti Pandas & NumPy Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Pandas & NumPy Academy?
Non è richiesta alcuna esperienza precedente. Pandas & NumPy Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Join sinistri e destri»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Pandas & NumPy Academy?
Sì. Ogni lezione Pandas & NumPy Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- pd.concat per impilare DataFrame
- pd.merge: join interno ed esterno
- Join sinistri e destri
- Eseguire join sull'indice