Розуміння inplace = True


109

У pandasбібліотеці багато разів є можливість змінити об'єкт замість нього, наприклад, з наступним твердженням ...

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

Мені цікаво, що повертається, а також як обробляється об'єкт, коли inplace=Trueпередається проти коли inplace=False.

Чи всі операції змінюються, selfколи inplace=True? І коли inplace=Falseнегайно створюється новий об’єкт, такий як new_df = selfі потім new_df, повертається?


14
Так, inplace=Trueфункція return None inplace=Falseповертає копію об’єкта з виконаною операцією. Документи з цим досить чіткі, чи є щось, що плутає з конкретною частиною? ЗокремаIf True, do operation inplace and return None.
EdChum

Я підкласую об'єкт DataFrame, і з такою операцією, як злиття, здається, неможливо зробити це замість ... self = self.merge(new_df, how='left', on='column2' Я не впевнений, що можливо перепризначити себе
Аран Фріл,

1
Ви праві, що DataFrame.merge не має inplaceаргументів. Він повертає DataFrame, тому жодна проблема не перепризначена.
JAV

Чи може хтось також виділити переваги його використання з точки зору споживання ресурсів?
markroxor

2
@markroxor Насправді їх не так багато. У декількох випадках inplaceдія може бути трохи швидшою, оскільки насправді не потрібно повертати копію результату. Але це все. Є більше причин, щоб не використовувати його.
cs95

Відповіді:


99

Після inplace=Trueпередачі дані перейменовуються на місце (вони нічого не повертають), тому ви використовуєте:

df.an_operation(inplace=True)

Коли inplace=Falseпередано (це значення за замовчуванням, тому не є необхідним), виконує операцію і повертає копію об'єкта, тому ви б використали:

df = df.an_operation(inplace=False) 

Чи маю я рацію, думаючи, що inplaceце варіант лише для методів, що змінюють існуючі дані, але не для методів, які "переробляють" дані. Наприклад, я можу .set_index (inplace = True), оскільки це застосовує значення до існуючого індексу, але не можу .reindex (inplace = True), оскільки це може створити додаткові рядки в DataFrame, яких не було в попередньому масиві ?
ac24

4
Метод .dropna()приймає inplace=Trueі, безумовно, може змінити фрейм даних, тому ні.
jorijnsmit

3
Тут потрібно бути обережним. @ ac24 насправді є більш-менш правильним. Поки dropnaповертає фрейм даних різної форми, він фактично не змінює базові дані - він просто повертає маску над ним (коли inplace=False), що може призвести до жаху SettingWithCopyWarning. Тільки тоді, коли більше не буде посилань на старий масив значень, панди зміняться відповідно до маски. Краще емпіричне правило: inplaceдоступне, коли операція не вимагає виділення нового резервного ndarray значень.
BallpointBen

49

В пандах inplace = True вважається шкідливим чи ні?

TLDR; Так, так це.

  • inplace, на відміну від того, що випливає з назви, часто не заважає створювати копії і (майже) ніколи не пропонує жодних переваг щодо продуктивності
  • inplace не працює з ланцюжком методів
  • inplace є загальною ловушкою для початківців, тому видалення цієї опції спростить API

Я не раджу встановлювати цей параметр, оскільки він мало корисний . Див. Цю проблему GitHub, де пропонується inplaceаргумент не підтримувати в api-масштабі.

Поширеною помилкою є те, що використання inplace=Trueпризведе до більш ефективного або оптимізованого коду. Насправді використання результатів абсолютно не впливає на продуктивністьinplace=True . Як версія на місці, так і не на місці створюють копію даних у будь-якому випадку , при цьому версія на місці автоматично призначає копію назад.

inplace=Trueє загальною ловушкою для початківців. Наприклад, це може викликати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

Виклик функції в стовпці DataFrame inplace=True може працювати, а може і не працювати . Це особливо вірно, коли задіяна ланцюгова індексація.

Наче описаних вище проблем недостатньо, це inplace=Trueтакож перешкоджає ланцюжку методів . Контраст робочому

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

На відміну від

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

Перший підходить для кращої організації коду та читабельності.


Ще одним підтверджуючим твердженням є те, що API для set_axisнещодавно був змінений таким чином, що inplaceзначення за замовчуванням було змінено з True на False. Див. GH27600 . Чудова робота розробників!


1
Звичайно, inplace=Trueце не працює з ланцюжком тощо, але це очевидно, ви розумієте, що це робить концептуально. Особисто я вважаю трохи чистішим, щоб уникнути призначення - Ви б також були за вилучення list.sortтощо зі стандартної бібліотеки?
Chris_Rands

4
Я не думаю, що це справедливе порівняння. Є очевидні переваги використання list.sort порівняно з сортуванням. Те саме стосується інших функцій на місці. Тут немає реальної вигоди, ланцюжок методів набагато частіше зустрічається у панд, і в будь-якому випадку планується знецінення цього аргументу.
cs95

Я також вважаю, що трохи чистіше уникати призначення: також, наприклад, python list.append()також є на місці, тоді як pandas df.append - ні (і навіть не підтримує на місці), що мене дратує до кінця. Ось чому я хотів би знати, лише щоб зрозуміти, що таке справжні переваги - які очевидні переваги використання list.sort проти відсортованого, крім уникнення призначення? В іншому випадку я думаю, що тут є справжня вигода - я можу уникати призначення, де я особисто вважаю це більш читабельним.
sdbbs

1
@sdbbs list.append()додає до існуючого списку. df.appendробить копію ваших даних (неважливо, у вас 5 рядків або 5 мільйонів), потім додає новий рядок до вашої копії, а потім повертає її. Як ви думаєте, що має більше сенсу? Що стосується df.append, ЗБІГАЙТЕСЯ СТОЛИ МОЖЛИВО . Я не думаю, що це хороший приклад аргументувати inplace = True, я навіть не думаю, що цій функції є місце в API.
cs95

46

Те, як я ним користуюся

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

Або

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

ВИСНОВОК:

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

5
Привіт @Nabin, це занадто зрозуміло для тих, хто працює над Pandas та Numpy :-)
Vetrivel PS

6

inplaceпараметр:

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

в Pandasі в цілому означає:

1. Pandas створює копію вихідних даних

2. ... робить деякі обчислення на ньому

3. ... присвоює результати вихідним даним.

4. ... видаляє копію.

Як ви можете прочитати в подальшій частині моєї відповіді нижче, ми все ще можемо мати вагомі причини використовувати цей параметр, тобто inplace operations, але ми повинні уникати його, якщо зможемо, оскільки це породжує більше проблем, як:

1. Ваш код буде важче налагодити (фактично SettingwithCopyWarning означає попередження про цю можливу проблему)

2. Конфлікт із ланцюжком методів


Тож є навіть випадок, коли ми мали б ним уже скористатися?

Безумовно, так. Якщо ми використовуємо панди або будь-який інструмент для обробки величезного набору даних, ми можемо легко зіткнутися з ситуацією, коли деякі великі дані можуть споживати всю нашу пам’ять. Щоб уникнути цього небажаного ефекту, ми можемо скористатися деякими методами, такими як ланцюжок методів :

(
    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"]]
)

які роблять наш код більш компактним (хоча його також важче інтерпретувати та налагоджувати) і споживають менше пам'яті, оскільки ланцюгові методи працюють із повернутими значеннями іншого методу, що призводить до отримання лише однієї копії вхідних даних. Ми чітко бачимо, що після цієї операції у нас буде 2 рази споживання оригінальної пам'яті.

Або ми можемо використовувати inplaceпараметр (хоча його теж важче інтерпретувати та налагоджувати). Наше споживання пам’яті становитиме 2 х вихідних даних , але споживання пам'яті після цієї операції залишається 1 х вихідних даних , що, якщо хтось, коли б працював з величезними наборами даних, точно знає, це може бути велика вигода.


Остаточний висновок:

Уникайте використання inplaceпараметра, якщо ви не працюєте з величезними даними та не знаєте про можливі проблеми у разі його використання.


2

Збережіть його до тієї ж змінної

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

Збережіть його в окрему змінну

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

Але ви завжди можете замінити змінну

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

FYI: За замовчуванням inplace = False


1

При спробі внести зміни до фрейму даних Pandas за допомогою функції, ми використовуємо 'inplace = True', якщо хочемо зафіксувати зміни у фреймі даних. Отже, перший рядок у наступному коді змінює назву першого стовпця в "df" на "Оцінки". Нам потрібно викликати базу даних, якщо ми хочемо побачити отриману базу даних.

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

Ми використовуємо 'inplace = False' (це також значення за замовчуванням), коли ми не хочемо фіксувати зміни, а просто друкуємо отриману базу даних. Отже, фактично копія вихідної бази даних із здійсненими змінами друкується без зміни вихідної бази даних.

Щоб бути більш зрозумілим, наступні коди роблять те саме:

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

0

inplace=True використовується залежно від того, чи хочете ви внести зміни до вихідного df чи ні.

df.drop_duplicates()

буде робити лише перегляд скинутих значень, але не вноситиме змін до df

df.drop_duplicates(inplace  = True)

знизить значення та внесе зміни до df.

Сподіваюся, це допомагає. :)


0

inplace=Trueробить функцію нечистою. Він змінює початковий кадр даних і повертає None. У такому випадку Ви розриваєте ланцюжок DSL. Оскільки більшість функцій фрейму даних повертають новий фрейм даних, ви можете зручно користуватися DSL. Подібно до

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

Виклик функції із inplace=Trueповерненням None та ланцюжком DSL порушено. Наприклад

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

кине NoneType object has no attribute 'rename'

Щось подібне із вбудованим сортуванням та сортуванням python. lst.sort()повертається Noneі sorted(lst)повертає новий список.

Як правило, не використовуйте, inplace=Trueякщо у вас немає конкретних причин для цього. Коли вам потрібно написати код перепризначення, наприклад df = df.sort_values(), спробуйте приєднати виклик функції в ланцюжку DSL, наприклад

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

надання точного робочого коду з належним форматуванням дійсно допоможе користувачам швидше зрозуміти вашу відповідь. Прохання зробити те саме. Я не фахівець з панд, тому не можу переформатувати вашу відповідь, але настійно рекомендую,
Ананд

0

Наскільки я маю досвід роботи з пандами, я хотів би відповісти.

Аргумент "inplace = True" означає фрейм даних, який повинен вносити зміни постійними, наприклад.

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

змінює той самий фрейм даних (оскільки ці панди знаходять записи NaN в індексі і скидають їх). Якщо ми спробуємо

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

pandas показує фрейм даних із внесеними нами змінами, але не змінить оригінальний фрейм даних "df".


0

Якщо ви не використовуєте inplace = True або ви використовуєте inplace = False, ви в основному отримуєте копію.

Так, наприклад:

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

змінить структуру з даними, відсортованими за спаданням.

тоді:

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

зробить testdf2 копією. всі значення будуть однаковими, але сортування буде змінено, і ви отримаєте незалежний об'єкт.

потім дано інший стовпець, скажімо LongMA, і ви робите:

testdf2.LongMA = testdf2.LongMA -1

стовпець LongMA у testdf матиме вихідні значення, а testdf2 - декриміновані значення.

Важливо відстежувати різницю, оскільки ланцюг обчислень зростає, а копії фреймів даних мають власний життєвий цикл.


0

Так, у Pandas у нас багато функцій має параметр, inplaceале за замовчуванням йому присвоюється False.

Отже, коли ви df.dropna(axis='index', how='all', inplace=False)це робите , ви думаєте, що не хочете змінювати оригінал DataFrame, тому він замість цього створює нову копію для вас із необхідними змінами.

Але, коли ви змінюєте inplaceпараметр наTrue

Тоді еквівалентно прямому сказанню, що я не хочу нової копії, DataFrameа замість цього вношу зміни до заданогоDataFrame

Це змушує інтерпретатор Python не створювати новийDataFrame

Але ви також можете уникнути використання inplaceпараметра, перепризначивши результат до оригінального DataFrame

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.