0Pricing
Pandas & NumPy Academy · Lezione

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 name

Struttura 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     Home

Join 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 differs

Confrontare 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           Home

Anti-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   NaN

Preservare 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 fewer

Verifica 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

  1. pd.concat per impilare DataFrame
  2. pd.merge: join interno ed esterno
  3. Join sinistri e destri
  4. Eseguire join sull'indice
← Torna a Pandas & NumPy Academy