apply() su colonne e righe
Usi DataFrame.apply() con axis=0 e axis=1 per eseguire una funzione personalizzata su ogni colonna o su ogni riga.
apply() su colonne e righe è una lezione Pandas & NumPy Academy gratuita su CoddyKit. Questa è la lezione 1 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.
Quando utilizzare apply()
DataFrame.apply() esegue una funzione Python personalizzata su ogni colonna (axis=0) o su ogni riga (axis=1). È lo strumento da usare come ultima risorsa, perché è più lento delle operazioni vettorializzate integrate, ma è essenziale quando un calcolo non può essere espresso tramite aritmetica NumPy, indicizzazione booleana o funzioni di aggregazione integrate. Lo utilizzi quando servono una logica condizionale complessa, un'analisi personalizzata delle stringhe o calcoli in più passaggi che operano su una sola riga o colonna alla volta.
import pandas as pd
import numpy as np
df = pd.DataFrame({
'price': [10.5, 25.0, 8.3, 100.0],
'quantity': [3, 1, 5, 2],
'tax_rate': [0.05, 0.10, 0.05, 0.15]
})
print(df)apply() sulle colonne (axis=0)
Con axis=0 (il valore predefinito), apply() passa ogni colonna alla funzione come Series. La funzione riceve una colonna alla volta e dovrebbe restituire uno scalare (per un'aggregazione) o una Series (per una trasformazione). Questo è utile per applicare con una sola chiamata una fase personalizzata di normalizzazione o pulizia a tutte le colonne numeriche.
# Custom range normalisation (0 to 1) for each column
def min_max_scale(col):
return (col - col.min()) / (col.max() - col.min())
df_scaled = df[['price', 'quantity']].apply(min_max_scale, axis=0)
print(df_scaled)apply() sulle righe (axis=1)
Con axis=1, apply() passa ogni riga alla funzione come Series. L'indice della riga corrisponde al nome della colonna, quindi è possibile accedere ai valori tramite il nome. Questa modalità è ideale per i calcoli a livello di riga che dipendono da più colonne, ad esempio il calcolo del ricavo totale dopo le imposte quando ogni riga ha la propria aliquota fiscale.
def revenue_after_tax(row):
subtotal = row['price'] * row['quantity']
return subtotal * (1 + row['tax_rate'])
df['revenue_after_tax'] = df.apply(revenue_after_tax, axis=1)
print(df)Restituzione di più valori con apply()
Una funzione passata a apply(axis=1) può restituire una pd.Series con elementi denominati, che Pandas espande in più nuove colonne. È più chiaro che chiamare apply() due volte per ottenere due nuove colonne. In alternativa, la funzione può restituire un dict, che Pandas espande anch'esso in colonne.
def compute_totals(row):
subtotal = row['price'] * row['quantity']
tax = subtotal * row['tax_rate']
return pd.Series({'subtotal': subtotal, 'tax': tax, 'total': subtotal + tax})
result = df.apply(compute_totals, axis=1)
print(result)apply() per aggregazioni personalizzate sulle colonne
Utilizzi apply(func, axis=0) per calcolare una statistica personalizzata per ogni colonna e restituire una Series riepilogativa. Ad esempio, può calcolare in un'unica chiamata il coefficiente di variazione (deviazione standard divisa per la media) per ogni colonna numerica. Il risultato è una Series indicizzata per nome della colonna, utile per una diagnostica rapida colonna per colonna.
def coeff_of_variation(col):
return col.std() / col.mean() if col.mean() != 0 else np.nan
cv = df[['price', 'quantity']].apply(coeff_of_variation, axis=0)
print('Coefficient of variation per column:')
print(cv)Confronto tra apply() e le alternative vettorializzate
Prima di utilizzare apply(), verifichi sempre se esiste un'alternativa vettorializzata. Per il calcolo del ricavo dopo le imposte, df['price'] * df['quantity'] * (1 + df['tax_rate']) esegue la stessa operazione della versione con apply(axis=1), ma è da 10 a 100 volte più veloce perché utilizza cicli a livello C di NumPy. Riservi apply() ai casi in cui la logica vettorializzata risulterebbe illeggibilmente complessa.
import time
start = time.time()
df['vectorised'] = df['price'] * df['quantity'] * (1 + df['tax_rate'])
print('Vectorised:', time.time() - start, 's')
start = time.time()
df['apply_result'] = df.apply(revenue_after_tax, axis=1)
print('apply():', time.time() - start, 's')apply() con una lambda
Per trasformazioni brevi su una sola riga, passi direttamente una lambda a apply() invece di definire una funzione denominata. Le lambda sono concise per le operazioni semplici, ma dovrebbero essere evitate per la logica complessa, per la quale una funzione denominata con commenti è più facile da comprendere e testare. Utilizzi le lambda con moderazione: non è facile sottoporle a test unitari o analizzarle tramite profilazione per nome.
# Clip revenue between 0 and 200, then round to nearest 10
df['revenue_clean'] = df['revenue_after_tax'].apply(lambda x: round(min(max(x, 0), 200) / 10) * 10)
print(df[['revenue_after_tax', 'revenue_clean']])Passaggio di argomenti aggiuntivi a apply()
Passi argomenti aggiuntivi alla funzione utilizzando la tupla args o argomenti con nome in apply(func, args=(val,), axis=1). In questo modo evita di utilizzare variabili globali all'interno della funzione e la rende riutilizzabile con valori dei parametri diversi. In Python 3.8 e versioni successive, può anche utilizzare functools.partial per creare una versione parzialmente applicata della funzione.
def discount_price(row, discount_pct, threshold):
if row['quantity'] >= threshold:
return row['price'] * (1 - discount_pct)
return row['price']
df['discounted_price'] = df.apply(
discount_price, axis=1,
args=(0.1, 3) # 10% discount for quantity >= 3
)
print(df[['price', 'quantity', 'discounted_price']])apply() per la conversione dei tipi
Quando una colonna contiene tipi misti — alcuni interi, alcuni numeri con virgola mobile e alcune stringhe — astype() genera un errore. Utilizzi apply(pd.to_numeric, errors='coerce') per tentare la conversione riga per riga e restituire NaN per i valori che non possono essere convertiti. Questo è un modello sicuro per le colonne che dovrebbero essere numeriche, ma contengono occasionalmente elementi non numerici dovuti a errori di inserimento.
messy = pd.Series(['10', '20.5', 'N/A', '100', '--'])
clean = messy.apply(pd.to_numeric, errors='coerce')
print(clean)Prestazioni: apply() vs np.vectorize
Quando una funzione applicata a scalari deve essere applicata elemento per elemento, np.vectorize(func)(array) è in genere più veloce di Series.apply(func), perché la vectorize di NumPy utilizza un meccanismo di dispatch tramite C invece dell'overhead delle chiamate di funzione di Python. Tuttavia, np.vectorize è comunque più lenta del vero broadcasting: è utile solo quando nessuna espressione di broadcasting riesce a rappresentare la logica.
def classify_size(price):
if price < 15:
return 'small'
elif price < 50:
return 'medium'
return 'large'
# np.vectorize approach
classify_v = np.vectorize(classify_size)
df['size_class'] = classify_v(df['price'].values)
print(df[['price', 'size_class']])Quando apply() è la scelta giusta
Apply è lo strumento giusto quando: (1) la logica richiede diramazioni simultanee sui valori di più colonne; (2) la funzione chiama un'API esterna o un database per ogni riga (un'operazione inevitabilmente sequenziale); (3) la funzione analizza una stringa complessa, come un oggetto JSON memorizzato in una cella; oppure (4) la funzione restituisce un oggetto di lunghezza variabile, come una lista. In tutti gli altri casi, preferisca le operazioni vettorializzate per ottenere maggiore velocità e leggibilità.
import json
# Parse a JSON metadata column row by row
df['metadata'] = ['{"color": "red"}', '{"color": "blue"}', '{}', '{"color": "green"}']
df['color'] = df['metadata'].apply(lambda s: json.loads(s).get('color', 'unknown'))
print(df[['metadata', 'color']])Controllo rapido
Verifichi la Sua comprensione dei concetti di analisi dei dati trattati in questa lezione.
Riepilogo della lezione
In questa lezione ha imparato a: usare apply(axis=0) per calcolare statistiche personalizzate a livello di colonna, usare apply(axis=1) per eseguire calcoli a livello di riga con più colonne di input e riconoscere quando preferire alternative vettorializzate per ottenere prestazioni migliori. Prossimamente esploreremo apply() con GroupBy per aggregazioni complesse a livello di gruppo.
Impara Python con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 30
- Lezioni
- 120
Domande Frequenti
La lezione «apply() su colonne e righe» è gratuita?
Sì — il testo completo di «apply() su colonne e righe» è 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 «apply() su colonne e righe»?
Usi DataFrame.apply() con axis=0 e axis=1 per eseguire una funzione personalizzata su ogni colonna o su ogni riga. 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 1 di 4.
Quanto tempo richiede la lezione «apply() su colonne e righe»?
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
- apply() su colonne e righe
- apply() con GroupBy
- map() e applymap() per operazioni elemento per elemento
- Concatenare metodi con pipe()