在 np.where 条件下使用 pandas 可为空的整数 dtype
Posted
技术标签:
【中文标题】在 np.where 条件下使用 pandas 可为空的整数 dtype【英文标题】:Using pandas nullable integer dtype in np.where condition 【发布时间】:2022-01-03 04:21:04 【问题描述】:我有一个 DataFrame 下面有一些缺失值。
df = pd.DataFrame(data=[['A', 1, None], ['B', 2, 5]],
columns=['X', 'Y', 'Z'])
由于df['Z']
应该是一个整数列,我将其数据类型更改为pandas
新实验类型nullable integer如下。
ydf['Z'] = ydf['Z'].astype(pd.Int32Dtype())
ydf
X Y Z
0 A 1 <NA>
1 B 2 5
现在我正在尝试使用简单的numpy
where 方法使用下面的代码将df['Z']
列中的非空值替换为固定整数值(例如1
)。
np.where(pd.isna(ydf['Z']), pd.NA, np.where(ydf['Z'] > 0, 1, 0))
但我收到以下错误,我无法理解为什么,因为我已经在检查第一个条件中具有空值的行。
TypeError: boolean value of NA is ambiguous
【问题讨论】:
np.where(ydf['Z'] > 0, 1, 0)
抛出错误。
是的,我知道,但为什么呢?
我认为 np.where
只需要一个布尔数组,但 ydf['Z'] > 0
返回像 <NA>
这样的 nans
是的,df['Z'] > 0
(其中 df
是原始 df,在将其转换为新的 Int32 类型之前)为 nan 返回 False
。
明白。这就说得通了。谢谢。
【参考方案1】:
正如@user17242583 所建议的,np.where
只需要一个布尔值数组,但您的比较返回一个三态数组:True
、False
和 <NA>
。
>>> df['Z'] > 0
0 <NA>
1 True
Name: Z, dtype: boolean
在这种情况下,np.where
无法决定返回值是否应解释为 True
或 False
。
随意投递你的专栏:
>>> np.where(pd.isna(df['Z']), pd.NA, np.where(df['Z'].astype(float) > 0, 1, 0))
array([<NA>, 1], dtype=object)
【讨论】:
【参考方案2】:np.where
需要一个布尔数组。使用int64
dtype,在系列上使用>
会为nans 返回False
。使用 Int32
dtype(注意大写 I
),>
不会将 nans 强制为 False,因此会出现错误。
一种解决方案是使用ydf['Z'].gt(0).fillna(False)
而不是ydf['Z'] > 0
。 (它们是一样的,第二个只是将 NA 更改为 False):
np.where(pd.isna(ydf['Z']), pd.NA, np.where(ydf['Z'].gt(0).fillna(False), 1, 0))
【讨论】:
快速提问。第二个np.where
条件不应该只考虑在我检查NA
的第一个条件中被拒绝为False
的行。否则,嵌套条件的意义何在。【参考方案3】:
一个可能有用的选项是 pyjanitor 中的 case_when 函数,它可以帮助处理嵌套表达式,也适用于 Pandas 扩展数组类型:
# pip install pyjanitor
import pandas as pd
import janitor
df.case_when(
df.Z.isna(), df.Z, # condition, result
df.Z.gt(0), 1,
0, # default value if False
column_name='Z')
X Y Z
0 A 1 <NA>
1 B 2 1
【讨论】:
以上是关于在 np.where 条件下使用 pandas 可为空的整数 dtype的主要内容,如果未能解决你的问题,请参考以下文章
Pandas 掩码 / where 方法与 NumPy np.where
使用 np.where() 在 pandas 数据框中将 True/False 值更改为离散值
pandas新字段(数据列)生成使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战