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?
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__'. –
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ą. –
Dzięki @ c.leather. Ciekawe, jakie są te kontrole. – Alex