inplace=True 不适用于子集数据

rou*_*dan 3 python

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

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

data.loc[mark,'Surface']=data.loc[mark,'Surface'].fillna(value='TEST')
Run Code Online (Sandbox Code Playgroud)

这是我的代码

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)
Run Code Online (Sandbox Code Playgroud)

这个正在工作:

data.loc[mark,'Surface']=data.loc[mark,'Surface'].fillna(value='TEST')
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

Cam*_*ell 5

您在这里遇到的主要问题是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
Run Code Online (Sandbox Code Playgroud)

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

>>> df.loc[10:15, "Surface"]._is_view
True
Run Code Online (Sandbox Code Playgroud)

现在这仍然无法解决您的问题,因为您填充的值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
..  ...      ...
Run Code Online (Sandbox Code Playgroud)

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

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

>>> df.loc[bool_mask, "Surface"] = df.loc[bool_mask, "Surface"].fillna("Test")
Run Code Online (Sandbox Code Playgroud)

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