Considera il seguente frame di dati:
A B C D
0 foo one 0.162003 0.087469
1 bar one -1.156319 -1.526272
2 foo two 0.833892 -1.666304
3 bar three -2.026673 -0.322057
4 foo two 0.411452 -0.954371
5 bar two 0.765878 -0.095968
6 foo one -0.654890 0.678091
7 foo three -1.789842 -1.130922
I seguenti comandi funzionano:
> df.groupby('A').apply(lambda x: (x['C'] - x['D']))
> df.groupby('A').apply(lambda x: (x['C'] - x['D']).mean())
ma nessuno dei seguenti lavori:
> df.groupby('A').transform(lambda x: (x['C'] - x['D']))
ValueError: could not broadcast input array from shape (5) into shape (5,3)
> df.groupby('A').transform(lambda x: (x['C'] - x['D']).mean())
TypeError: cannot concatenate a non-NDFrame object
Perché? L'esempio sulla documentazione sembra suggerire che la chiamata transform
a un gruppo consente di eseguire l'elaborazione delle operazioni per riga:
# Note that the following suggests row-wise operation (x.mean is the column mean)
zscore = lambda x: (x - x.mean()) / x.std()
transformed = ts.groupby(key).transform(zscore)
In altre parole, ho pensato che la trasformazione sia essenzialmente un tipo specifico di applicazione (quello che non si aggrega). Dove sbaglio?
Per riferimento, di seguito è riportata la costruzione del frame di dati originale sopra:
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C' : randn(8), 'D' : randn(8)})
zscore
), transform
riceve una funzione lambda che presuppone che ciascuno di essi x
sia un elemento all'interno di group
e restituisca anche un valore per elemento nel gruppo. Cosa mi sto perdendo?
apply
passa nell'intero df, ma transform
passa ciascuna colonna singolarmente come una serie. 2) apply
può restituire qualsiasi output di forma (scalare / Serie / DataFrame / array / elenco ...), mentre transform
deve restituire una sequenza (Serie 1D / array / elenco) della stessa lunghezza del gruppo. Ecco perché apply()
non è necessario il PO transform()
. Questa è una buona domanda poiché il documento non ha spiegato chiaramente entrambe le differenze. (simile alla distinzione tra apply/map/applymap
, o altre cose ...)
transform
deve restituire un numero, una riga o la stessa forma dell'argomento. se è un numero, il numero verrà impostato su tutti gli elementi del gruppo, se è una riga, verrà trasmesso a tutte le righe del gruppo. Nel tuo codice, la funzione lambda restituisce una colonna che non può essere trasmessa al gruppo.