Python 熊猫在现场操作中的应用
我期待着一种奇怪的行为。在下面的代码中Python 熊猫在现场操作中的应用,python,pandas,in-place,Python,Pandas,In Place,我期待着一种奇怪的行为。在下面的代码中 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 _dro
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
创建了一个副本,我正在修改原始序列):
但是当dropna(inplace=True)
操作应该在原地完成,从而修改原始序列,但是我得到的结果是:
a b c
0 -1.0 -1.0 -1.0
1 5.8 NaN NaN
不过,我希望结果与以前的情况相同。dropna
操作是否返回克隆,即使该操作已就位?
我使用的是熊猫版本0.23.1
编辑:
根据提供的答案,我添加了hex(ids())
调用来验证实际实例。上面的代码对此进行了打印(值可能不同,但它们之间的相等性应该相同)
奇怪的是,该函数在a
和b
列上被调用了2次,但是该函数表示只在第一列上调用了两次
此外,列b
第二遍的十六进制值不同。当省略列drop()
时,这两种情况都不会发生
十六进制值表明,<代码> .Apple()>代码>创建了一个新的列副本,但是它如何将这些值传播回原来的<代码> df>代码>我不知道。
我试图用可变范围的概念来解释这一点,不认为它是一个完整的答案,但对其他人来说可能是有洞察力的。p>当.apply在与col参数对应的每个系列上执行时,在_drop()行col[0]=-1的范围内,全局更改df的“第一行”,因此它会对其进行变异。当使用inplace=True调用dropna()时,实际会删除nan,但仅针对该函数范围内的序列,它不会分配给全局df。即使它覆盖了变量col。另一个洞察可能是Docs说.dropna(inplace=True)返回None,_drop()也将返回None,因为没有return语句 在pandas/numpy github上提出这个问题可能是值得的-对我来说,这看起来像是意外的行为-如果您向函数添加
return col
语句,您的代码将按预期工作。这表明确实创建了本地副本<代码>打印(十六进制(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)
def_下降(col):
列[0]=-1
col.dropna(就地=真)
列[0]=1
return col#你期望你的期望输出是什么?请参考这篇文章了解inplace@J先生:这篇文章并没有回答作者的问题……这是一个有趣的问题——如果你在函数中添加两次print(hex(id(col))
,你会发现没有复制done@Thomas它讨论了inplace是如何工作的。是的,这种方法是有效的,但是行df.apply(\u drop)
创建了一个新的数据帧。原始的df
与我的问题一样保留为-1。这可能就是id不同的原因。如前所述,我建议在上提出一个问题。即使这不是一个bug,也绝对是意外行为。如果你提出了问题,请在这里发布链接,我也对结果感兴趣。行col[0]=-1
不会全局更改df的第一行,但只更改col
系列中的第一行(这是df中的一个特定元素)。我更新了我的代码,您可以看到,变量col
在删除后没有修改。最后,我看不到任何与返回类型的连接,无论是.dropna(inplace=True)
还是\u drop()。
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
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)