Панды - это на месте = Правда считается вредным или нет?
Это обсуждалось ранее, но с противоречивыми ответами:
Что мне интересно, так это:
- Почему
inplace = False
поведение по умолчанию? - Когда это хорошо изменить? (ну, мне разрешено это изменить, так что я думаю, что есть причина).
- Это проблема безопасности? то есть, может ли операция потерпеть неудачу / плохо себя вести из-за
inplace = True
? - Могу ли я знать заранее, если определенный
inplace = True
операция "реально" будет проводиться на месте?
Мой вывод так далеко:
- Многие операции Панд имеют
inplace
параметр, всегда по умолчаниюFalse
Это означает, что исходный DataFrame не тронут, и операция возвращает новый DF. - При настройке
inplace = True
операция может работать с исходным DF, но она все равно может работать с копией за кулисами и просто переназначить ссылку после завершения.
плюсы inplace = False
:
- Разрешает цепной / функциональный синтаксис:
df.dropna().rename().sum()...
это приятно, и дает возможность для ленивой оценки или более эффективного повторного заказа (хотя я не думаю, что Панда делает это). - Когда используешь
inplace = True
на объекте, который потенциально является срезом / представлением нижележащего DF, Pandas должен сделатьSettingWithCopy
проверить, что дорого.inplace = False
избегает этого - Последовательное и предсказуемое поведение за кадром.
плюсы inplace = True
:
- Может быть как быстрее, так и меньше занимать память (первая ссылка показывает
reset_index()
работает в два раза быстрее и использует половину пиковой памяти!).
Таким образом, оставляя в стороне проблему копирования-просмотра, кажется более производительным всегда использовать inplace = True
, если специально не написание цепного заявления. Но это не по умолчанию Панды, так что мне не хватает?
1 ответ
В пандах inplace = True считается вредным или нет?
Да. Не просто вредно. Довольно вредно. В этом выпуске GitHub предлагаетсяinplace
Аргумент будет устаревшим для api-wide в ближайшем будущем. Вкратце, здесь все не так сinplace
аргумент:
inplace
, вопреки тому, что следует из названия, часто не препятствует созданию копий и (почти) никогда не дает никаких преимуществ в производительностиinplace
не работает с цепочкой методовinplace
является распространенной ошибкой для новичков, поэтому удаление этой опции упростит API
Производительность.
Распространенное заблуждение, что использованиеinplace=True
приведет к более эффективному или оптимизированному коду. В целом нет, там нет преимущества производительности в использовании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()
Непреднамеренные ловушки
Еще одно предостережение, о котором следует помнить, - это призыв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
Что может вызвать неожиданное поведение.
Если inplace
по умолчанию, тогда DataFrame будет мутирован для всех имен, которые в данный момент ссылаются на него.
Простой пример, скажем, у меня есть df
:
df = pd.DataFrame({'a': [3, 2, 1], 'b': ['x', 'y', 'z']})
Теперь очень важно, чтобы DataFrame сохранил этот порядок строк - скажем, это из источника данных, где порядок вставки является ключевым, например.
Однако теперь мне нужно выполнить некоторые операции, требующие другого порядка сортировки:
def f(frame):
df = frame.sort_values('a')
# if we did frame.sort_values('a', inplace=True) here without
# making it explicit - our caller is going to wonder what happened
# do something
return df
Это нормально - мой оригинал df
остается такой же. Однако если inplace=True
были по умолчанию, то мой оригинал df
теперь будет отсортирован как побочный эффект f()
в котором я должен был бы доверять вызывающему, чтобы помнить, что он не делает что-то на месте, которое я не ожидаю, вместо того, чтобы преднамеренно делать что-то на месте... Так что лучше, чтобы все, что может мутировать объект на месте, делало это явно в хотя бы сделай более очевидным, что случилось и почему.
Даже с основными встроенными в Python мутаблями вы можете наблюдать это:
data = [3, 2, 1]
def f(lst):
lst.sort()
# I meant lst = sorted(lst)
for item in lst:
print(item)
f(data)
for item in data:
print(item)
# huh!? What happened to my data - why's it not 3, 2, 1?