Zrozumienie w miejscu = prawda


109

W pandasbibliotece wielokrotnie istnieje możliwość zmiany obiektu w miejscu np. Za pomocą poniższej instrukcji ...

df.dropna(axis='index', how='all', inplace=True)

Jestem ciekawy, co jest zwracane oraz jak obiekt jest obsługiwany, kiedy inplace=Truejest przekazywany, a kiedy inplace=False.

Czy wszystkie operacje modyfikują selfkiedy inplace=True? A kiedy inplace=Falsenowy obiekt jest tworzony natychmiast, na przykład, new_df = selfa następnie new_dfjest zwracany?


14
Tak, inplace=Truezwraca None inplace=Falsezwraca kopię obiektu z wykonaną operacją. Dokumenty są dość jasne na ten temat, czy jest coś, co jest mylące z określoną częścią? SpeficallyIf True, do operation inplace and return None.
EdChum

Podklasuję obiekt DataFrame i przy operacji takiej jak scalanie nie wydaje się możliwe zrobienie tego w miejscu ... self = self.merge(new_df, how='left', on='column2' Nie jestem pewien, czy jest możliwe ponowne przypisanie siebie
Aran Freel

1
Masz rację, że DataFrame.merge nie ma inplaceargumentu. Zwraca DataFrame, więc nie ma problemu z ponownym przypisaniem.
JAV

Czy ktoś może również wskazać zalety korzystania z niego w zakresie zużycia zasobów?
markroxor

2
@markroxor Naprawdę nie ma ich wielu. W kilku przypadkach inplaceakcja może być trochę szybsza, ponieważ w rzeczywistości nie musisz zwracać kopii wyniku. Ale to jest o tym. Powodów, aby go nie używać, jest o wiele więcej.
cs95

Odpowiedzi:


99

Po inplace=Trueprzekazaniu dane są zmieniane w miejscu (nic nie zwraca), więc użyjesz:

df.an_operation(inplace=True)

Kiedy inplace=Falsejest przekazywane (jest to wartość domyślna, więc nie jest to konieczne), wykonuje operację i zwraca kopię obiektu, więc użyjesz:

df = df.an_operation(inplace=False) 

Czy miałbym rację sądząc, że inplacejest to tylko opcja dla metod, które zmieniają istniejące dane, ale nie dla metod, które „przekształcają” dane? Na przykład mogę .set_index (inplace = True), ponieważ dotyczy to wartości do istniejącego indeksu, ale nie może .reindex (inplace = True), ponieważ może to spowodować utworzenie dodatkowych wierszy w DataFrame, które nie istniały w poprzedniej tablicy ?
ac24

4
Metoda .dropna()akceptuje inplace=Truei zdecydowanie może zmienić kształt ramki danych, więc nie.
jorijnsmit

3
Tutaj trzeba uważać. @ ac24 ma właściwie mniej więcej rację. Chociaż dropnazwraca ramkę danych o innym kształcie, w rzeczywistości nie zmienia kształtu danych podstawowych - po prostu zwraca maskę nad nią (kiedy inplace=False), co może prowadzić do przerażenia SettingWithCopyWarning. Tylko wtedy, gdy nie ma już odniesień do starej tablicy wartości, pandy zmieniają kształt zgodnie z maską. Lepsza inplacepraktyczna zasada jest następująca: jest dostępna, gdy operacja nie wymaga przydzielania nowego zapasowego ndarray wartości.
BallpointBen

49

Czy w pandach inplace = True jest uważany za szkodliwy, czy nie?

TLDR; Tak tak to jest.

  • inplacewbrew temu, co sugeruje nazwa, często nie uniemożliwia tworzenia kopii i (prawie) nigdy nie zapewnia żadnych korzyści związanych z wydajnością
  • inplace nie działa z łączeniem metod
  • inplace to częsta pułapka dla początkujących, więc usunięcie tej opcji uprości interfejs API

Nie radzę ustawiać tego parametru, ponieważ ma to niewielki cel . Zobacz ten problem z usługą GitHub, który proponuje inplacewycofanie argumentu w całym api.

Powszechnym błędem jest przekonanie, że używanie inplace=Trueprowadzi do bardziej wydajnego lub zoptymalizowanego kodu. W rzeczywistości używanie nie daje żadnych korzyści w zakresie wydajnościinplace=True . Zarówno w miejscu i out-of-place wersje utworzyć kopię danych w każdym razie , ze wersja na miejscu automatycznie przypisując kopiowania plecy.

inplace=Trueto częsta pułapka dla początkujących. Na przykład może wywołaćSettingWithCopyWarning :

df = pd.DataFrame({'a': [3, 2, 1], 'b': ['x', 'y', 'z']})

df2 = df[df['a'] > 1]
df2['b'].replace({'x': 'abc'}, inplace=True)
# SettingWithCopyWarning: 
# A value is trying to be set on a copy of a slice from a DataFrame

Wywołanie funkcji w kolumnie DataFrame z inplace=True może, ale nie musi, działać . Jest to szczególnie ważne w przypadku indeksowania łańcuchowego.

Jakby opisane powyżej problemy nie wystarczały, utrudniainplace=True również łączenie metod . Porównaj działanie

result = df.some_function1().reset_index().some_function2()

W przeciwieństwie do

temp = df.some_function1()
temp.reset_index(inplace=True)
result = temp.some_function2()

Pierwsza z nich zapewnia lepszą organizację i czytelność kodu.


Innym potwierdzającym twierdzeniem jest to, że API for set_axiszostało niedawno zmienione w taki sposób, że inplacewartość domyślna została zmieniona z True na False. Zobacz GH27600 . Świetna robota!


1
Oczywiście inplace=Truenie działa z łańcuchem itp., Ale oczywiste jest, że rozumiesz, co to robi koncepcyjnie. Osobiście uważam, że unikanie przypisywania jest trochę czystsze. Czy byłbyś również zwolennikiem usunięcia list.sortitp. Z biblioteki standardowej?
Chris_Rands,

4
Nie sądzę, żeby to było uczciwe porównanie. Istnieje kilka oczywistych zalet używania list.sort w porównaniu z sortowaniem. To samo dotyczy innych funkcji lokalnych. Nie ma tu żadnej realnej korzyści, łączenie metod jest znacznie bardziej powszechne w pandach, a mimo to istnieją plany wycofania tego argumentu.
cs95

Uważam też, że jest trochę czystszy, aby uniknąć przypisania: również, na przykład, Python list.append()jest również na miejscu, podczas gdy pandas df.append nie (i nie obsługuje nawet inplace), co mnie irytuje bez końca. Dlatego chciałbym wiedzieć, żeby tylko zrozumieć, jakie są rzeczywiste korzyści - jakie są oczywiste korzyści z używania list.sort versus sort, poza unikaniem przypisywania? W przeciwnym razie myślę, że jest to prawdziwa korzyść - mogę uniknąć przypisania, gdy osobiście uważam to za bardziej czytelne.
sdbbs

1
@sdbbs zostanie dołączony list.append()do istniejącej listy. df.appendtworzy kopię danych (nie ma znaczenia, czy masz 5 wierszy czy 5 milionów), następnie dodaje nowy wiersz do kopii, a następnie zwraca go. Jak myślisz, co ma większy sens? Jeśli chodzi o df.append, UNIKAJ JAK NAJWIĘKSZEJ . Nie sądzę, że jest to dobry przykład argumentowania za inplace = True, nie sądzę nawet, że ta funkcja ma miejsce w API.
cs95

46

Sposób, w jaki go używam, jest

# Have to assign back to dataframe (because it is a new copy)
df = df.some_operation(inplace=False) 

Lub

# No need to assign back to dataframe (because it is on the same copy)
df.some_operation(inplace=True)

WNIOSEK:

 if inplace is False
      Assign to a new variable;
 else
      No need to assign

5
Cześć @Nabin, To zbyt jasne dla każdego, kto pracuje nad Pandami i Numpy :-)
Vetrivel PS,

6

inplaceParametr:

df.dropna(axis='index', how='all', inplace=True)

w Pandasogólności oznacza:

1. Pandas tworzy kopię oryginalnych danych

2. ... wykonuje jakieś obliczenia

3. ... przypisuje wyniki do oryginalnych danych.

4. ... usuwa kopię.

Jak możesz przeczytać w dalszej części mojej odpowiedzi poniżej, nadal możemy mieć dobry powód, aby używać tego parametru, tj. inplace operations, Ale powinniśmy go unikać, jeśli możemy, ponieważ generuje więcej problemów, takich jak:

1. Twój kod będzie trudniejszy do debugowania (w rzeczywistości SettingwithCopyWarning oznacza ostrzeżenie o tym możliwym problemie)

2. Konflikt z łączeniem metod


Więc jest nawet przypadek, kiedy powinniśmy go jeszcze użyć?

Zdecydowanie tak. Jeśli użyjemy pand lub dowolnego narzędzia do obsługi ogromnego zbioru danych, możemy łatwo stawić czoła sytuacji, w której niektóre duże zbiory danych mogą pochłonąć całą naszą pamięć. Aby uniknąć tego niepożądanego efektu, możemy użyć kilku technik, takich jak łączenie metod :

(
    wine.rename(columns={"color_intensity": "ci"})
    .assign(color_filter=lambda x: np.where((x.hue > 1) & (x.ci > 7), 1, 0))
    .query("alcohol > 14 and color_filter == 1")
    .sort_values("alcohol", ascending=False)
    .reset_index(drop=True)
    .loc[:, ["alcohol", "ci", "hue"]]
)

co sprawia, że ​​nasz kod jest bardziej zwarty (choć trudniejszy do zinterpretowania i debugowania) i zużywa mniej pamięci, ponieważ metody łańcuchowe działają z wartościami zwracanymi przez inną metodę, w wyniku czego powstaje tylko jedna kopia danych wejściowych. Widzimy wyraźnie, że po tych operacjach będziemy mieć 2 x pierwotne zużycie pamięci danych .

Lub możemy użyć inplaceparametru (choć trudniej też zinterpretować i debugować), nasze zużycie pamięci wyniesie 2 x oryginalne dane , ale nasze zużycie pamięci po tej operacji pozostanie 1 x oryginalne dane , które jeśli ktoś kiedykolwiek pracował z ogromnymi zbiorami danych dokładnie wie, może być duża korzyść.


Ostateczna konkluzja:

Unikaj używania inplaceparametru, chyba że nie pracujesz z dużymi danymi i pamiętaj o możliwych problemach, jeśli nadal go używasz.


2

Zapisz go w tej samej zmiennej

data["column01"].where(data["column01"]< 5, inplace=True)

Zapisz go w osobnej zmiennej

data["column02"] = data["column01"].where(data["column1"]< 5)

Ale zawsze możesz nadpisać zmienną

data["column01"] = data["column01"].where(data["column1"]< 5)

FYI: Domyślnie inplace = False


1

Kiedy próbujemy wprowadzić zmiany w ramce danych Pandas za pomocą funkcji, używamy „inplace = True”, jeśli chcemy zatwierdzić zmiany w ramce danych. Dlatego pierwszy wiersz w poniższym kodzie zmienia nazwę pierwszej kolumny w „df” na „Grades”. Musimy zadzwonić do bazy danych, jeśli chcemy zobaczyć wynikową bazę danych.

df.rename(columns={0: 'Grades'}, inplace=True)
df

Używamy „inplace = False” (jest to również wartość domyślna), gdy nie chcemy zatwierdzać zmian, ale po prostu drukujemy wynikową bazę danych. W efekcie kopia oryginalnej bazy danych z zatwierdzonymi zmianami jest drukowana bez zmiany oryginalnej bazy danych.

Dla większej jasności poniższe kody robią to samo:

#Code 1
df.rename(columns={0: 'Grades'}, inplace=True)
#Code 2
df=df.rename(columns={0: 'Grades'}, inplace=False}

0

inplace=True jest używany w zależności od tego, czy chcesz wprowadzić zmiany w oryginalnym df, czy nie.

df.drop_duplicates()

pokaże tylko usunięte wartości, ale nie wprowadzi żadnych zmian w df

df.drop_duplicates(inplace  = True)

porzuci wartości i wprowadzi zmiany w df.

Mam nadzieję że to pomoże.:)


0

inplace=Trueczyni funkcję nieczystą. Zmienia oryginalną ramkę danych i zwraca Brak. W takim przypadku Ty przerywasz łańcuch DSL. Ponieważ większość funkcji dataframe zwraca nową ramkę danych, można wygodnie korzystać z DSL. Lubić

df.sort_values().rename().to_csv()

Wywołanie funkcji z inplace=Truezwraca Brak i łańcuch DSL jest uszkodzony. Na przykład

df.sort_values(inplace=True).rename().to_csv()

rzuci NoneType object has no attribute 'rename'

Coś podobnego z wbudowanym sortowaniem i sortowaniem w Pythonie. lst.sort()zwraca Nonei sorted(lst)zwraca nową listę.

Generalnie nie używaj, inplace=Truechyba że masz ku temu konkretny powód. Kiedy musisz napisać kod ponownego przypisania, taki jak df = df.sort_values(), spróbuj dołączyć wywołanie funkcji w łańcuchu DSL, np

df = pd.read_csv().sort_values()...

podanie dokładnego działającego kodu z odpowiednim formatowaniem naprawdę pomoże użytkownikom szybciej zrozumieć Twoją odpowiedź. Prośba o zrobienie tego samego. Nie jestem ekspertem od pand, więc nie mogę sformatować odpowiedzi, ale jest to bardzo zalecane,
Anand Vaidya,

0

Jeśli chodzi o moje doświadczenie w pandach, chciałbym odpowiedzieć.

Argument „inplace = True” oznacza, że ​​ramka danych musi wprowadzić trwałe zmiany, np.

    df.dropna(axis='index', how='all', inplace=True)

zmienia tę samą ramkę danych (ponieważ ta panda znajduje wpisy NaN w indeksie i porzuca je). Jeśli spróbujemy

    df.dropna(axis='index', how='all')

pandas pokazuje ramkę danych ze zmianami, które wprowadzamy, ale nie modyfikuje oryginalnej ramki danych „df”.


0

Jeśli nie użyjesz inplace = True lub użyjesz inplace = False, w zasadzie otrzymasz kopię.

Na przykład:

testdf.sort_values(inplace=True, by='volume', ascending=False)

zmieni strukturę z danymi posortowanymi w porządku malejącym.

następnie:

testdf2 = testdf.sort_values( by='volume', ascending=True)

utworzy kopię testdf2. wszystkie wartości będą takie same, ale sortowanie zostanie odwrócone i będziesz mieć niezależny obiekt.

następnie biorąc pod uwagę kolejną kolumnę, powiedz LongMA i zrobisz:

testdf2.LongMA = testdf2.LongMA -1

kolumna LongMA w testdf będzie miała oryginalne wartości, a testdf2 będzie miała zdekrimentowane wartości.

Ważne jest, aby śledzić różnicę w miarę wzrostu łańcucha obliczeń, a kopie ramek danych mają swój własny cykl życia.


0

Tak, w Pandach mamy wiele funkcji, które mają parametr, inplaceale domyślnie jest do niego przypisany False.

Kiedy więc df.dropna(axis='index', how='all', inplace=False)to zrobisz , myśli, że nie chcesz zmieniać oryginału DataFrame, dlatego zamiast tego tworzy dla Ciebie nową kopię z wymaganymi zmianami.

Ale po zmianie inplaceparametru naTrue

Wtedy jest to równoważne z wyraźnym stwierdzeniem, że nie chcę nowej kopii DataFramezamiast tego dokonać zmian na podanymDataFrame

Zmusza to interpreter języka Python, aby nie tworzył nowego plikuDataFrame

Możesz też uniknąć używania inplaceparametru, ponownie przypisując wynik do oryginalnej ramki DataFrame

df = df.dropna(axis='index', how='all')

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.