在 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'] &gt; 0, 1, 0) 抛出错误。 是的,我知道,但为什么呢? 我认为 np.where 只需要一个布尔数组,但 ydf['Z'] &gt; 0 返回像 &lt;NA&gt; 这样的 nans 是的,df['Z'] &gt; 0(其中 df 是原始 df,在将其转换为新的 Int32 类型之前)为 nan 返回 False 明白。这就说得通了。谢谢。 【参考方案1】:

正如@user17242583 所建议的,np.where 只需要一个布尔值数组,但您的比较返回一个三态数组:TrueFalse&lt;NA&gt;

>>> df['Z'] > 0
0    <NA>
1    True
Name: Z, dtype: boolean

在这种情况下,np.where 无法决定返回值是否应解释为 TrueFalse

随意投递你的专栏:

>>> 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,在系列上使用&gt; 会为nans 返回False。使用 Int32 dtype(注意大写 I),&gt; 不会将 nans 强制为 False,因此会出现错误。

一种解决方案是使用ydf['Z'].gt(0).fillna(False) 而不是ydf['Z'] &gt; 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的主要内容,如果未能解决你的问题,请参考以下文章

使用 np.where 基于多列的 pandas 多个条件

Pandas 掩码 / where 方法与 NumPy np.where

使用 np.where() 在 pandas 数据框中将 True/False 值更改为离散值

pandas np.where 基于多索引级别

pandas新字段(数据列)生成使用np.where或者apply lambda函数结合if else生成新的字段,详解及实战

pandas比较两个dataframe特定数据列的数值是否相同并给出差值:使用np.where函数