熊猫 - 就位=真正被认为有害或无效?

时间:2017-08-08 14:24:31

标签: python pandas

之前已经讨论过,但答案相互矛盾:

我想知道的是:

  • 为什么inplace = False是默认行为?
  • 什么时候改变呢? (好吧,我允许改变它,所以我想这是一个原因)。
  • 这是安全问题吗?也就是说,由于inplace = True
  • ,操作是否会失败/行为不当
  • 我是否可以提前知道某项inplace = True操作是否真的会#34;是否就地进行?

我到目前为止:

  • 许多Pandas操作都有一个inplace参数,始终默认为False,这意味着原始DataFrame不受影响,并且操作返回一个新的DF。
  • 设置inplace = True时,操作可能可以在原始DF上运行,但它可能仍然可以在幕后复制,只需在完成后重新分配参考。

inplace = False的优点:

  • 允许链接/功能语法:df.dropna().rename().sum()...这很好,并提供了懒惰评估或更有效的重新排序的机会(虽然我不认为Pandas正在这样做)。
  • 对可能是基础DF的切片/视图的对象使用inplace = True时,Pandas必须进行SettingWithCopy检查,这是很昂贵的。 inplace = False避免这种情况。
  • 一致&幕后可预测的行为。

inplace = True的优点:

  • 可以更快,更少占用内存(第一个链接显示reset_index()运行速度提高一倍,使用峰值内存的一半!)。

因此,将copy-vs-view问题放在一边,除非专门编写链式语句,否则总是使用inplace = True似乎更有效。但那不是默认的熊猫选择,所以我错过了什么?

2 个答案:

答案 0 :(得分:17)

在熊猫中,inplace = True是否被认为有害?

是的。不仅有害。 相当有害。 This GitHub issue建议在不久的某个时候在API范围内弃用inplace参数。简而言之,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

这可能导致意外行为。

答案 1 :(得分:6)

如果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()的副作用,我必须信任调用者才能记住不做某事我没想到而不是故意做某事 ...所以最好能够改变一个对象的任何东西显式< / em>至少让事情变得更加明显和原因。

即使使用基本的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?