使用 numpy 数组与 DataFrame 屏蔽 Pandas DataFrame

Jus*_*tin 5 python numpy dataframe pandas

我想使用 2D 布尔掩码来选择性地更改pandas DataFrame. 我注意到我不能使用numpy数组(成功)作为掩码,但我可以使用DataFrame. 然而,更令人沮丧的是,我numpy方法没有出错

例如,

df = pd.DataFrame({'A':[1,2,3,4], 
                   'B':[10,20,30,40]})

mask_np = np.array([[True,True],
                    [False,False],
                    [True,False],
                    [False,True]])

mask_pd = pd.DataFrame(mask_np, columns=['A','B'])
Run Code Online (Sandbox Code Playgroud)

我认为任何一个掩码都会从df掩码所在的任何地方返回值True。但相反,df[mask_np]产生

   A   B
0  1  10
0  1  10
2  3  30
3  4  40
Run Code Online (Sandbox Code Playgroud)

这不是我所期望的,我也无法解释。另一方面, df[mask_pd]产生

     A     B
0  1.0  10.0
1  NaN   NaN
2  3.0   NaN
3  NaN  40.0
Run Code Online (Sandbox Code Playgroud)

这是我期望和想要的。

为什么我不能使用numpy口罩?我的互联网搜索没有发现任何相关内容。这种差异背后的任何解释将不胜感激!

[pandas版本 0.20.3; Python 3.6.3]

jpp*_*jpp 3

源代码说明了原因。该__getitem__方法[]是语法糖,专门通过数据帧检查索引:

elif isinstance(key, DataFrame):
    return self._getitem_frame(key)
Run Code Online (Sandbox Code Playgroud)

如果数据帧是布尔类型,则调用的方法_getitem_frame将返回:pd.DataFrame.where

def _getitem_frame(self, key):
    if key.values.size and not is_bool_dtype(key.values):
        raise ValueError('Must pass DataFrame with boolean values only')
    return self.where(key)
Run Code Online (Sandbox Code Playgroud)

NumPy 数组采用的路线_getitem_array不同且更加复杂。由于某种原因,代码被设计为以不同的方式处理 NumPy / Pandas 输入,而不是确保相同数据类型的一致性。


Pandas 数据帧的常规布尔索引通常沿轴应用,即通过行/轴 0df.loc[mask, :]或通过列/轴 1 df.loc[:, mask]

请注意,为了清楚起见,您可以而且可能应该pd.DataFrame.where直接访问:

res = df.where(mask_np)

print(res)

     A     B
0  1.0  10.0
1  NaN   NaN
2  3.0   NaN
3  NaN  40.0
Run Code Online (Sandbox Code Playgroud)