在Pandas身上,inplace=真的被认为是有害的吗?

2024-04-25 07:57:32 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我想知道的是:

  • 为什么inplace = False是默认行为
  • 什么时候换好?(嗯,我被允许改变它,所以我想这是有原因的)
  • 这是安全问题吗?也就是说,操作是否会由于inplace = True而失败/行为不当
  • 我是否可以提前知道某个inplace = True操作是否会“真正”执行到位

到目前为止,我的看法是:

  • 许多Pandas操作都有一个inplace参数,总是默认为False,这意味着原始数据帧未被触及,并且该操作返回一个新的DF
  • 当设置inplace = True时,操作可能对原始DF起作用,但它可能仍对幕后的副本起作用,完成后只需重新分配引用即可

{}的优点:

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

{}的优点:

  • 允许链式/函数式语法:df.dropna().rename().sum()...,这很好,并且提供了延迟计算或更有效的重新排序的机会(尽管我不认为Pandas正在这样做)
  • 当在可能是底层DF的切片/视图的对象上使用inplace = True时,Pandas必须执行SettingWithCopy检查,这很昂贵inplace = False避免了这种情况
  • 始终如一;可预测的幕后行为

因此,抛开复制与视图的问题不谈,似乎总是使用inplace = True更有效,除非专门编写链式语句。但这不是熊猫的默认选择,那么我错过了什么呢


Tags: 内存答案in视图falsetruepandasdf
2条回答

如果inplace是默认值,那么数据帧将针对当前引用它的所有名称进行变异

一个简单的例子,假设我有一个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?     

In pandas, is inplace = True considered harmful, or not?

是的。不仅仅是有害的非常有害This GitHub issue建议在不久的将来在api范围内弃用inplace参数。简言之,inplace参数的所有问题如下:

  • inplace与名称的含义相反,通常不会阻止创建副本,而且(几乎)从未提供任何性能优势
  • inplace不适用于方法链接
  • inplace在对数据帧列调用时可能导致可怕的SettingWithCopyWarning,有时可能无法就地更新该列

上面的痛点对于初学者来说都是常见的陷阱,因此删除此选项将大大简化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可以触发^{}

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

这可能会导致意外行为

相关问题 更多 >