首页 > 解决方案 > 标量值 isnull()/isnan()/isinf()

问题描述

在 Pandas 和 Numpy 中,有一些矢量化函数,如np.isnannp.isinf和 ,pd.isnull用于检查数组、系列或数据框的元素是否是各种缺失/空/无效的。

他们确实在标量上工作。pd.isnull(None)简单地返回True而不是pd.Series([True]),这很方便。

但是假设我想知道是否有任何对象是这些空值之一;您不能使用这些功能中的任何一个来做到这一点!那是因为他们很乐意对各种数据结构进行矢量化。不小心使用它们将不可避免地导致可怕的“系列的真值是模棱两可的”错误。

我想要的是这样的功能:

assert not is_scalar_null(3)
assert not is_scalar_null([1,2])
assert not is_scalar_null([None, 1])
assert not is_scalar_null(pd.Series([None, 1]))
assert not is_scalar_null(pd.Series([None, None]))
assert is_scalar_null(None)
assert is_scalar_null(np.nan)

在内部,Pandas 函数pandas._lib.missing.checknull会做正确的事情:

import pandas._libs.missing as libmissing
libmissing.checknull(pd.Series([1,2]))  # correctly returns False

但是使用它通常是不好的做法。根据 Python 命名约定,_lib是私有的。我也不确定 Numpy 的等价物。

是否有一种“可接受的”但正式的方式来使用与 NumPy 和 Pandas 相同的空检查逻辑,但仅限于标量?

标签: pythonpandasnumpymissing-data

解决方案


您所要做的就是pd.isnull以一种方式包装,以防万一它获得可迭代,它将被迫逐个检查它。这样,您将始终获得标量布尔值作为输出。

from collections import Iterable

def is_scalar_null(value):
    if isinstance(value, Iterable):
        return all(not pd.isnull(v) for v in value)
    return not pd.isnull(value)

assert is_scalar_null(3)
assert is_scalar_null([1, 2])
assert is_scalar_null(pd.Series([1]))
assert not is_scalar_null(None)
assert not is_scalar_null(np.nan)
assert not is_scalar_null([np.nan, 1])
assert not is_scalar_null(pd.Series([np.nan, 1]))

然后你可以修补实际的pd.isnull,但我不能说我建议这样做。

from collections import Iterable

orig_pd_is_null = pd.isnull

def is_scalar_null(value):
    if isinstance(value, Iterable):
        return all(not orig_pd_is_null(v) for v in value)
    return not orig_pd_is_null(value)

pd.isnull = is_scalar_null

assert pd.isnull(3)
assert pd.isnull([1, 2])
assert pd.isnull(pd.Series([1]))
assert not pd.isnull(None)
assert not pd.isnull(np.nan)
assert not pd.isnull([np.nan, 1])
assert not pd.isnull(pd.Series([np.nan, 1]))

这种方法可能会在嵌套迭代的情况下中断,但这可以通过在is_scalar_null.


推荐阅读