2016-07-01 23 views
12
import timeit 
import pandas as pd 
import numpy as np 

df = pd.DataFrame(np.random.rand(10, 10)) 

dft = df[[True, False] * 5] 
# df = dft 
dft2 = dft.copy() 

new_data = np.random.rand(5, 10) 

print(timeit.timeit('dft.loc[:, :] = new_data', setup='from __main__ import dft, new_data', number=100)) 
print(timeit.timeit('dft2.loc[:, :] = new_data', setup='from __main__ import dft2, new_data', number=100)) 

Sui miei valori di impostazione computer portatile in dft (il sottoinsieme originale) è di circa 160 volte più lento di impostazione dei valori in dft2 (una copia completa di dft).valori Impostazione su Pandas dataframe sottoinsieme (copia) è lento

Perché è questo il caso?

Modifica: Rimossa la speculazione sugli oggetti proxy.

Come c. suggerisce la pelle, probabilmente a causa di un diverso codepath quando si impostano i valori su una copia (dft) rispetto a un dataframe originale (dft2).

Domanda bonus: rimuovendo il riferimento al DataFrame originale df (disattendendo la riga df = dft), il fattore di velocità si riduce a circa 2 sul mio laptop. Qualche idea sul perché questo è il caso?

+2

Sotto il cofano, 'df [[True, False] * 5]' chiama 'Dataframe .__ getitem __()' che chiama 'Dataframe._getitem_array()' quando l'indicizzatore è una lista. Questo a sua volta chiama 'Dataframe.take()', che ha una proprietà is_copy. Ho scoperto che se eseguo 'df.take ([0,2,4,6,8], is_copy = True)', ottengo velocità più lente di 'df.take ([0,2,4,6, 8], is_copy = False) ', con is_copy = True produce runtime uguale a dft nel tuo esempio, e is_copy = False produce runtime uguale a dft2. Quindi, il rallentamento si verifica da qualche parte lungo la linea a causa di questa proprietà is_copy, forse durante 'Dataframe .__ setitem__'. –

+2

Ciò che la proprietà is_copy è effettivamente utilizzata, tuttavia, è piuttosto torbida, e probabilmente ci vorrà un po 'di scavo in '__setitem__'. Penso che la tua opinione sull'array restituito sia una vista/proxy è buona, e penso che abbia a che fare con questa proprietà. –

+0

Grazie @ c.leather. Mi chiedo cosa siano quei controlli. – Alex

risposta

4

Questa non è esattamente una nuova domanda su SO. This e this sono post correlati. This is the link to the current docs che lo spiega.

I commenti di @ c.leather sono sulla strada giusta. Il problema è che dft è una vista, non una copia del dataframe df, come spiegato negli articoli collegati. Ma i panda non possono sapere se è davvero o meno una copia e se l'operazione è sicura o meno, e come tale ci sono molti controlli in corso per garantire che sia sicuro eseguire l'incarico, e che potrebbe essere evitato semplicemente fare una copia.

Questo è un problema pertinente e c'è un'intera discussione allo Github. Ho visto molti suggerimenti, quello che mi piace di più è che i documenti dovrebbero incoraggiare l'idioma df[[True,False] * 5].copy(), uno potrebbe chiamarlo l'idioma della copia &.

Non sono riuscito a trovare i controlli esatti e sul problema github questa sfumatura di prestazioni è menzionata solo attraverso alcuni tweet che alcuni sviluppatori hanno pubblicato osservando il comportamento. Forse qualcuno più coinvolto nello sviluppo dei panda può aggiungere qualche input in più.

+1

La domanda non riguarda la vista o la copia, è la ragione della differenza di velocità. Penso che la mia speculazione sugli oggetti proxy sia fuorviante (e la sto facendo notare). Grazie per i link alla pagina di GitHub! – Alex