inplace=True不适用于子集数据

我正在尝试填充行子集中的缺失值。我正在使用inplace=Truein fillna(),但它在 jupyter notebook 中不起作用。您可以在 Surface 列的前 2 行中看到显示 NaN 的附加图片。我不知道为什么?

我必须这样做,所以它正在工作。为什么?感谢您的帮助。

data.loc[mark,'Surface']=data.loc[mark,'Surface'].fillna(value='TEST')
data.loc[mark,'Surface']=data.loc[mark,'Surface'].fillna(value='TEST')

这是我的代码

mark=(data['Pad']==51) | (data['Pad']==52) | (data['Pad']==53) | (data['Pad']==54) | (data['Pad']==55)

data.loc[mark,'Surface'].fillna(value='TEST',inplace=True)

这个正在工作:

回答

您在这里遇到的主要问题是pandas没有非常明确的视图与复制规则。您的结果向我表明这里的问题.loc是返回副本而不是视图。虽然 pandas 确实尝试从 返回视图.loc,但有很多注意事项。

在玩了一会儿之后,似乎使用布尔/位置索引掩码返回一个副本 - 您可以使用私有_is_view属性验证这一点:

import pandas as pd
import numpy as np

df = pd.DataFrame({"Pad": range(40, 60), "Surface": np.nan})

print(df)
   Pad  Surface
0   40      NaN
1   41      NaN
2   42      NaN
.  ...      ...
19  59      NaN


# Create masks
bool_mask = df["Pad"].isin(range(51, 56))
positional_mask = np.where(bool_mask)[0]

# Check `_is_view` after simple .loc:
>>> df.loc[bool_mask, "Surface"]._is_view
False

>>> df.loc[positional_mask, "Surface"]._is_view
False

因此,上述两种方法都没有返回原始数据的“视图”,这就是执行inplace操作不会更改原始数据帧的原因。为了从.loc您那里返回视图,您需要使用切片作为行索引。

>>> df.loc[10:15, "Surface"]._is_view
True

现在这仍然无法解决您的问题,因为您填充的值NaN可能会或可能不会更改dtype“表面”列的 。在我设置的示例中,“Surface”有一个 float64 dtype- 并且通过填充NaN值“Test”,您将强制该 dtype 更改,这与原始数据帧不兼容。如果您的“表面”列是objectdtype,那么您无需担心这一点。

>>> df.dtypes
Pad          int64
Surface    float64

# this does not work because "Test" is incompatible with float64 dtype
>>> df.loc[10:15, "Surface"].fillna("Test", inplace=True)

# this works because 0.9 is an appropriate value for a float64 dtype
>>> df.loc[10:15, "Surface"].fillna(0.9, inplace=True)
>>> print(df)
    Pad  Surface
..  ...      ...
8    48      NaN
9    49      NaN
10   50      0.9
11   51      0.9
12   52      0.9
13   53      0.9
14   54      0.9
15   55      0.9
16   56      NaN
17   57      NaN
..  ...      ...

TLDR;一般不要依赖inplace熊猫。在其大部分操作中,它仍会创建底层数据的副本,然后尝试用新副本替换原始数据源。Pandas 的内存效率不高,所以如果你担心内存性能,你可能想切换到像Vaex这样从头开始设计为零复制的东西,而不是试图通过Pandas。

您分配数据帧切片的方法是最合适的,并且将确保您收到将数据帧更新为“就地”的正确结果:

>>> df.loc[bool_mask, "Surface"] = df.loc[bool_mask, "Surface"].fillna("Test")

  • 这是一个很好的发现,并且与正常的 numpy 行为一致:在 numpy 中返回掩码或花哨索引的视图是没有意义的。

以上是inplace=True不适用于子集数据的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>