我期待一种奇怪的熊猫行为。在以下代码中
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()
。
答案 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)