【问题标题】:Boolean mask of None vs NaN in array of arrays数组数组中 None 与 NaN 的布尔掩码
【发布时间】:2021-03-09 16:09:12
【问题描述】:

我想在具有混合数据类型的 NumPy 数组中区分 None 和 NaN。具体来说,我想使用一些元素是数组的数组。例如,假设我有以下混合数据类型的数组,但没有数组元素:

arr = np.array([[1,    None,      3],
                [4,       5, np.nan],
                [7, 'eight',     9]])

我可以使用以下内容检查 None 的值:

>>> arr == None

array([[False,  True, False],
       [False, False, False],
       [False, False, False]])

这得到了我想要的结果:一个布尔掩码,其中包含有关各个元素的信息,说明哪些元素是None。但是,当数组中的任何元素是另一个数组时,上面的 sn-p 不起作用。例如,考虑另一个数组:

arr_elem = np.array([3,3,3])
arr = np.array([[1,    None,      arr_elem],
                [4,       5,        np.nan],
                [7, 'eight',             9]])

现在,我得到一个布尔值,而不是布尔掩码:

>>> arr == None

False

什么是获取布尔掩码的矢量化方法,该掩码表示数组中哪些元素是 None 而不是 NaN?

【问题讨论】:

    标签: python numpy multidimensional-array boolean numpy-ndarray


    【解决方案1】:

    您有一个对象 dtype 数组。 numpy 数组在 dtype 为数字时是最好的——无论是速度还是操作范围。

    除此之外,Nonenp.nan 的测试和数组的相等性测试也存在问题。

    is NoneNone 的最佳测试。 np.isnan 是对nan 的最佳测试,因为没有任何东西等于nan,甚至不等于它本身。并且对数组的相等性测试会产生布尔数组和ambiguity 错误。

    In [58]: arr = np.array([[1,    None,      3],
        ...:                 [4,       5, np.nan],
        ...:                 [7, 'eight',     9]])
    In [59]: arr
    Out[59]: 
    array([[1, None, 3],
           [4, 5, nan],
           [7, 'eight', 9]], dtype=object)
    In [60]: arr == None
    Out[60]: 
    array([[False,  True, False],
           [False, False, False],
           [False, False, False]])
    

    好的,None 测试可以,但nan 不行:

    In [61]: arr == np.nan
    Out[61]: 
    array([[False, False, False],
           [False, False, False],
           [False, False, False]])
    In [62]: np.isnan(arr)
    Traceback (most recent call last):
      File "<ipython-input-62-25d2f1dae78d>", line 1, in <module>
        np.isnan(arr)
    TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
    

    isnan 适用于 float dtype 数组,而不是 object dtype。

    使用数组元素创建数组会产生警告。那是因为从混合长度的数组中创建一个数组通常是一个错误。

    In [63]: arr_elem = np.array([3,3,3])
        ...: arr1 = np.array([[1,    None,      arr_elem],
        ...:                 [4,       5,        np.nan],
        ...:                 [7, 'eight',             9]])
    <ipython-input-63-6d36e87ab1a9>:2: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
      arr1 = np.array([[1,    None,      arr_elem],
    In [64]: arr1
    Out[64]: 
    array([[1, None, array([3, 3, 3])],
           [4, 5, nan],
           [7, 'eight', 9]], dtype=object)
    

    和以前一样,这是一个对象 dtype 数组,只是元素是一个数组。

    In [65]: arr1 == None
    <ipython-input-65-2a40a08151e4>:1: DeprecationWarning: elementwise comparison failed; this will raise an error in the future.
      arr1 == None
    Out[65]: False
    

    它必须对每个元素进行== 测试。但是应用于数组元素的测试会产生一个布尔数组(与In[60] 相同)

    In [66]: arr_elem==None
    Out[66]: array([False, False, False])
    

    【讨论】:

    • 感谢您的回复。对不起,但我认为这不能回答我的问题。我知道比较适用于None,但不适用于np.nan。我知道当前应用于数组数组的测试会产生一个布尔值 (False)。我不知道(并且需要知道!)是如何从数组数组中获取布尔掩码/数组,其中布尔掩码/数组中的每个元素对应于原始数组中的一个元素。有人知道这样做的方法吗?
    • 我也知道这是一个非常极端的情况,不是 NumPy 数组的设计目的。但我碰巧不得不使用数组。
    • 你可以写一个函数来处理一个元素的所有这些情况,然后用np.frompyfunc将它应用到整个数组,你有太多的特殊情况来处理现有的代码。
    • 哦,这太棒了!非常感谢。如果您将其写为答案,我会接受。关于性能,我只想做一个简单的检查elem is None。如果用np.frompyfunc 应用于整个数组,你认为这会很慢吗?
    • 使用 object dtype 所有操作都或多或少地以列表理解速度。
    猜你喜欢
    • 2015-11-03
    • 2016-11-22
    • 1970-01-01
    • 2018-10-02
    • 2020-02-14
    • 1970-01-01
    • 2013-11-27
    • 2020-01-14
    • 2018-01-26
    相关资源
    最近更新 更多