在 np.where 条件下使用 pandas 可空整数 dtype
Using pandas nullable integer dtype in np.where condition
我下面有一个 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
正如@user17242583 所建议的那样,np.where
只需要一个布尔值数组,但您的比较 return 是一个三态数组:True
、False
和 <NA>
.
>>> df['Z'] > 0
0 <NA>
1 True
Name: Z, dtype: boolean
在这种情况下,np.where
无法决定 returned 值应该被解释为 True
还是 False
。
只需即时投射您的专栏:
>>> np.where(pd.isna(df['Z']), pd.NA, np.where(df['Z'].astype(float) > 0, 1, 0))
array([<NA>, 1], dtype=object)
np.where
需要一个布尔值数组。使用 int64
dtype,在系列 returns False
上使用 >
作为 nans。使用 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))
case_when function from pyjanitor 可能对这里有帮助的一个选项,它可以帮助嵌套表达式,也适用于 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
我下面有一个 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
正如@user17242583 所建议的那样,np.where
只需要一个布尔值数组,但您的比较 return 是一个三态数组:True
、False
和 <NA>
.
>>> df['Z'] > 0
0 <NA>
1 True
Name: Z, dtype: boolean
在这种情况下,np.where
无法决定 returned 值应该被解释为 True
还是 False
。
只需即时投射您的专栏:
>>> np.where(pd.isna(df['Z']), pd.NA, np.where(df['Z'].astype(float) > 0, 1, 0))
array([<NA>, 1], dtype=object)
np.where
需要一个布尔值数组。使用 int64
dtype,在系列 returns False
上使用 >
作为 nans。使用 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))
case_when function from pyjanitor 可能对这里有帮助的一个选项,它可以帮助嵌套表达式,也适用于 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