Quali regole usa Panda per generare una vista rispetto a una copia?


119

Sono confuso riguardo alle regole che Pandas usa quando decide che una selezione da un dataframe è una copia del dataframe originale o una vista sull'originale.

Se ho, ad esempio,

df = pd.DataFrame(np.random.randn(8,8), columns=list('ABCDEFGH'), index=range(1,9))

Capisco che a queryrestituisce una copia in modo che qualcosa di simile

foo = df.query('2 < index <= 5')
foo.loc[:,'E'] = 40

non avrà alcun effetto sul dataframe originale, df. Capisco anche che le sezioni scalari o denominate restituiscono una vista, in modo che le assegnazioni a queste, come

df.iloc[3] = 70

o

df.ix[1,'B':'E'] = 222

cambierà df. Ma sono perso quando si tratta di casi più complicati. Per esempio,

df[df.C <= df.B] = 7654321

cambia df, ma

df[df.C <= df.B].ix[:,'B':'E']

non.

C'è una semplice regola che Panda sta usando che mi manca solo? Cosa sta succedendo in questi casi specifici; e in particolare, come faccio a modificare tutti i valori (o un sottoinsieme di valori) in un dataframe che soddisfano una particolare query (come sto tentando di fare nell'ultimo esempio sopra)?


Nota: questa non è la stessa di questa domanda ; e ho letto la documentazione , ma non ne sono illuminato. Ho anche letto le domande "correlate" su questo argomento, ma mi manca ancora la semplice regola utilizzata da Panda e come la applicherei, ad esempio, per modificare i valori (o un sottoinsieme di valori) in un dataframe che soddisfa una particolare query.

Risposte:


138

Ecco le regole, sostituzione successiva:

  • Tutte le operazioni generano una copia

  • Se inplace=Trueviene fornito, verrà modificato sul posto; solo alcune operazioni lo supportano

  • Un indicizzatore che imposta, ad esempio, .loc/.iloc/.iat/.atsi posizionerà.

  • Un indicizzatore che ottiene un oggetto di tipo singolo è quasi sempre una vista (a seconda del layout della memoria potrebbe non essere per questo motivo non affidabile). Questo è principalmente per l'efficienza. (l'esempio sopra è per .query; questo restituirà sempre una copia come valutata da numexpr)

  • Un indicizzatore che ottiene su un oggetto a più caratteri è sempre una copia.

Il tuo esempio di chained indexing

df[df.C <= df.B].loc[:,'B':'E']

non è garantito che funzioni (e quindi non dovresti mai farlo).

Invece fai:

df.loc[df.C <= df.B, 'B':'E']

poiché è più veloce e funzionerà sempre

L'indicizzazione concatenata è composta da 2 operazioni Python separate e quindi non può essere intercettata in modo affidabile dai panda (spesso ne otterrai una SettingWithCopyWarning, ma non è neppure rilevabile al 100%). I documenti di sviluppo , che hai indicato, offrono una spiegazione molto più completa.


3
.queryrestituirà SEMPRE una copia a causa di ciò che sta facendo (e non una vista), perché è valutata da n numexpr. Quindi lo aggiungerò alle "regole"
Jeff

3
pandas si affida a numpy per determinare se viene generata una visualizzazione. In un singolo caso dtype (che potrebbe essere un 1-d per una serie, un 2-d per un frame, ecc.). numpy può generare una vista; dipende da cosa stai affettando; a volte puoi avere una visuale ea volte no. pandas non si basa affatto su questo fatto poiché non è sempre ovvio se viene generata una visualizzazione. ma questo non importa in quanto loc non si basa su questo durante l'impostazione. Tuttavia, quando l'indicizzazione a catena è molto importante (e quindi perché l'indicizzazione a catena è sbagliata)
Jeff

3
Molte grazie Jeff, la tua risposta è molto utile. Qual è la tua fonte / riferimento su questo argomento?
Kamixave

4
Allora prima, grazie per il tuo ottimo lavoro! In secondo luogo, se hai abbastanza tempo, penso che sarebbe fantastico aggiungere un paragrafo simile alla tua risposta principale nel documento.
Kamixave

2
certamente prenderebbe una richiesta pull per aggiungere / rivedere i documenti. Fallo.
Jeff
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.