熊猫就地操作适用

时间:2018-07-16 09:02:56

标签: python pandas in-place

我期待一种奇怪的熊猫行为。在以下代码中

userItemsHandler := userContextHandler(itemConextHandler(ItemGET))
r.Handle("/users/{username}/items/{itemId}", userItemsHandler).Methods("PUT")

如果我注释掉import numpy as np import pandas as pd def info(df): print(f"whole df: {hex(id(df))}") print(f"col a : {hex(id(df['a']))}") print(f"col b : {hex(id(df['b']))}") print(f"col c : {hex(id(df['c']))}") def _drop(col): print(f"called on : {col.name}") print(f"before drop: {hex(id(col))}") col[0] = -1 col.dropna(inplace=True) col[0] = 1 print(f"after drop : {hex(id(col))}") df = pd.DataFrame([[np.nan, 1.2, np.nan], [5.8, np.nan, np.nan]], columns=['a', 'b', 'c']) info(df) df.apply(_drop) info(df) 行或致电dropna(),则会得到预期的结果(因为dropna(inplace=False)创建了一个副本,而我正在修改原始系列):

dropna

但是当 a b c 0 1.0 1.0 1.0 1 5.8 NaN NaN 时,该操作应就地完成,从而修改了原始序列,但得到的结果是:

dropna(inplace=True)

但是,我希望结果与以前的情况相同。 a b c 0 -1.0 -1.0 -1.0 1 5.8 NaN NaN 操作是否在原位返回克隆? 我正在使用0.23.1版的熊猫。

编辑: 根据提供的答案,我添加了dropna调用以验证实际实例。上面的代码印有此内容(值可能对您来说有所不同,但它们之间的相等性应该相同)

hex(ids())

奇怪的是,该函数在列whole df : 0x1f482392f28 col a : 0x1f482392f60 col b : 0x1f48452af98 col c : 0x1f48452ada0 called on : a before drop: 0x1f480dcc2e8 after drop : 0x1f480dcc2e8 called on : b before drop: 0x1f480dcc2e8 after drop : 0x1f480dcc2e8 called on : a before drop: 0x1f480dcc2e8 after drop : 0x1f480dcc2e8 called on : b before drop: 0x1f4ffef1ef0 after drop : 0x1f4ffef1ef0 called on : c before drop: 0x1f480dcc2e8 after drop : 0x1f480dcc2e8 whole df : 0x1f482392f28 col a : 0x1f482392f60 col b : 0x1f48452af98 col c : 0x1f48452ada0 a上被调用了两次,但是docs说该函数仅在第一列上被调用了两次。

此外,列b的第二遍的十六进制值是不同的。省略b时,两者都不会发生。

十六进制值表明col.drop()创建了列的新副本,但是我不知道它如何将值传播回原始.apply()

2 个答案:

答案 0 :(得分:0)

我尝试使用可变范围的概念来对此进行推理,不会认为这是一个完整的答案,但也许对其他人很有见地。

当在与col参数相对应的每个系列上执行.apply时,在_drop()行的范围内col [0] = -1全局更改df的“第一行”,因此将其突变。当使用inplace = True调用dropna()时,实际上会删除NaN,但仅针对该函数范围内的序列,不会将其分配给全局df。即使它覆盖变量col。另一个见解可能是Docs说.dropna(inplace = True)返回None,而_drop()也返回None,因为没有return语句。

答案 1 :(得分:0)

可能值得在pandas / numpy github上引发此问题-对我来说,这似乎是意外行为-如果向函数添加return col语句,您的代码将按预期工作。这表明确实创建了本地副本。 print(hex(id(col)))确认了这一点。

def _drop(col):
    col[0] = -1
    col.dropna(inplace=True)
    col[0] = 1
    return col # <----

df = pd.DataFrame([[np.nan, 1.2, np.nan],
                   [5.8, np.nan, np.nan]], columns=['a', 'b', 'c'])

df.apply(_drop)