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]
源代码说明了原因。该__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)