在 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 是一个三态数组:TrueFalse<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