Assegnazione di colonne super semplice
Un frame di dati panda è implementato come un ordine ordinato di colonne.
Ciò significa che __getitem__
[]
non può essere utilizzato solo per ottenere una determinata colonna, ma __setitem__
[] =
può essere utilizzato per assegnare una nuova colonna.
Ad esempio, questo frame di dati può avere una colonna aggiunta semplicemente usando l' []
accessor
size name color
0 big rose red
1 small violet blue
2 small tulip red
3 small harebell blue
df['protected'] = ['no', 'no', 'no', 'yes']
size name color protected
0 big rose red no
1 small violet blue no
2 small tulip red no
3 small harebell blue yes
Si noti che funziona anche se l'indice del frame di dati è disattivato.
df.index = [3,2,1,0]
df['protected'] = ['no', 'no', 'no', 'yes']
size name color protected
3 big rose red no
2 small violet blue no
1 small tulip red no
0 small harebell blue yes
[] = è la strada da percorrere, ma attenzione!
Tuttavia, se si dispone di un pd.Series
e si tenta di assegnarlo a un frame di dati in cui gli indici sono disattivati, si verificherà un problema. Vedi esempio:
df['protected'] = pd.Series(['no', 'no', 'no', 'yes'])
size name color protected
3 big rose red yes
2 small violet blue no
1 small tulip red no
0 small harebell blue no
Questo perché a pd.Series
di default ha un indice elencato da 0 a n. E il [] =
metodo panda cerca di essere "intelligente"
Cosa sta realmente succedendo.
Quando si utilizza il [] =
metodo panda esegue silenziosamente un join esterno o unione esterna utilizzando l'indice del frame di dati sinistro e l'indice delle serie di destra.df['column'] = series
Nota a margine
Ciò provoca rapidamente dissonanza cognitiva, poiché il []=
metodo sta cercando di fare molte cose diverse a seconda dell'input e il risultato non può essere previsto a meno che non si sappia semplicemente come funzionano i panda. Vorrei quindi sconsigliare le []=
basi di codice in, ma quando si esplorano i dati in un notebook, va bene.
Aggirare il problema
Se hai un pd.Series
e lo desideri assegnato dall'alto verso il basso, o se stai codificando un codice produttivo e non sei sicuro dell'ordine dell'indice, vale la pena salvaguardarlo per questo tipo di problema.
È possibile pd.Series
eseguire il downcast di a np.ndarray
o a list
, questo farà il trucco.
df['protected'] = pd.Series(['no', 'no', 'no', 'yes']).values
o
df['protected'] = list(pd.Series(['no', 'no', 'no', 'yes']))
Ma questo non è molto esplicito.
Alcuni programmatori potrebbero arrivare e dire "Ehi, sembra ridondante, lo ottimizzerò semplicemente".
Modo esplicito
L'impostazione dell'indice di pd.Series
come indice di df
è esplicita.
df['protected'] = pd.Series(['no', 'no', 'no', 'yes'], index=df.index)
O più realisticamente, probabilmente ne hai pd.Series
già uno disponibile.
protected_series = pd.Series(['no', 'no', 'no', 'yes'])
protected_series.index = df.index
3 no
2 no
1 no
0 yes
Ora può essere assegnato
df['protected'] = protected_series
size name color protected
3 big rose red no
2 small violet blue no
1 small tulip red no
0 small harebell blue yes
Modo alternativo con df.reset_index()
Poiché la dissonanza dell'indice è il problema, se ritieni che l'indice del frame di dati non debba dettare le cose, puoi semplicemente rilasciare l'indice, questo dovrebbe essere più veloce, ma non è molto pulito, poiché la tua funzione ora probabilmente fa due cose.
df.reset_index(drop=True)
protected_series.reset_index(drop=True)
df['protected'] = protected_series
size name color protected
0 big rose red no
1 small violet blue no
2 small tulip red no
3 small harebell blue yes
Nota su df.assign
Mentre df.assign
rendi più esplicito ciò che stai facendo, in realtà ha tutti gli stessi problemi di cui sopra[]=
df.assign(protected=pd.Series(['no', 'no', 'no', 'yes']))
size name color protected
3 big rose red yes
2 small violet blue no
1 small tulip red no
0 small harebell blue no
Fai attenzione a df.assign
che la tua colonna non viene chiamata self
. Causerà errori. Questo rende df.assign
puzzolente , dal momento che ci sono questo tipo di artefatti nella funzione.
df.assign(self=pd.Series(['no', 'no', 'no', 'yes'])
TypeError: assign() got multiple values for keyword argument 'self'
Potresti dire "Bene, non userò self
allora". Ma chissà come questa funzione cambierà in futuro per supportare nuovi argomenti. Forse il nome della tua colonna sarà un argomento in un nuovo aggiornamento di Panda, causando problemi con l'aggiornamento.