2016-07-01 9 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)) 

Na moich wartości ustawień laptopów w dft (oryginał podzbiór) jest około 160 razy wolniej niż ustawienie wartości w dft2 (głęboka kopia dft).wartości ustawienie na Pandy DataFrame podzbioru (kopia) jest powolny

Dlaczego tak się dzieje?

Edytuj: Usunięto spekulacje na temat obiektów proxy.

Jako c. sugeruje skóra, jest to prawdopodobnie spowodowane inną ścieżką kodowania podczas ustawiania wartości na kopii (dft) w porównaniu z oryginalną ramką danych (dft2).

Dodatkowe pytanie: usunięcie odniesienia do oryginalnej ramki DataFrame df (przez odkomentowanie linii df = dft), zmniejsza współczynnik prędkości do około 2 na moim laptopie. Czy masz jakieś pojęcie, dlaczego tak się dzieje?

+2

Pod maską: 'df [[True, False] * 5]' wywołuje 'Dataframe .__ getitem __()', która wywołuje 'Dataframe._getitem_array()', gdy indeksator jest listą. To z kolei wywołuje 'Dataframe.take()', która ma właściwość is_copy. Odkryłem, że jeśli uruchomię 'df.take ([0,2,4,6,8], is_copy = True), otrzymam prędkości wolniejsze niż' df.take ([0,2,4,6, 8], is_copy = False) ', z is_copy = True produkując równe środowisko uruchomieniowe do dft w twoim przykładzie, i is_copy = False produkuje równe środowisko wykonawcze do dft2. Tak więc spowolnienie pojawia się gdzieś w dół z powodu tej właściwości is_copy, być może podczas 'Dataframe .__ setitem__'. –

+2

To, do czego jest używana właściwość is_copy, jest jednak dość mętne i prawdopodobnie zajmie trochę wykopywania w '__setitem__'. Myślę, że twoje wrażenie, że zwrócona tablica jest widokiem/proxy, jest dobre i myślę, że ma to związek z tą właściwością. –

+0

Dzięki @ c.leather. Ciekawe, jakie są te kontrole. – Alex

Odpowiedz

4

To nie jest nowe pytanie na SO. This i this są powiązane posty. This is the link to the current docs który to wyjaśnia.

Komentarze od @ c.leather są na właściwej ścieżce. Problem polega na tym, że dft jest widokiem, a nie kopią ramki danych df, jak wyjaśniono w połączonych artykułach. Ale pandy nie mogą wiedzieć, czy to naprawdę kopia, czy też operacja jest bezpieczna, czy też nie, i jako że jest wiele kontroli, aby upewnić się, że wykonanie zadania jest bezpieczne i można tego uniknąć, po prostu zrobienie kopii.

Jest to istotny problem i cała dyskusja jest dostępna pod adresem Github. Widziałem wiele sugestii, najbardziej podoba mi się to, że doktorzy powinni zachęcać do idiomu df[[True,False] * 5].copy(), można go nazwać kodem plastra &.

Nie mogłem znaleźć dokładnych czeków, a na problemie github ten niuans wydajności jest wspomniany tylko przez kilka tweetów napisanych przez kilku programistów, zwracających uwagę na zachowanie. Może ktoś bardziej zaangażowany w rozwój pandy może dodać więcej danych wejściowych.

+1

Pytanie nie dotyczy widoku a kopii, chodzi o przyczynę różnicy prędkości. Myślę, że moje spekulacje na temat obiektów proxy są mylące (i wybijam je). Dzięki za linki do strony github! – Alex

Powiązane problemy