【问题标题】:Using pandas nullable integer dtype in np.where condition在 np.where 条件下使用 pandas 可为空的整数 dtype
【发布时间】: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
  • 明白。这就说得通了。谢谢。

标签: python pandas numpy boolean missing-data


【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2017-02-02
      • 1970-01-01
      • 2016-08-04
      • 1970-01-01
      • 2022-12-02
      • 1970-01-01
      • 1970-01-01
      • 2017-11-18
      • 2021-12-18
      相关资源
      最近更新 更多