【问题标题】:Check for uniformity of a multidimensional list检查多维列表的一致性
【发布时间】:2019-04-08 07:59:45
【问题描述】:

在我的other question 之后,我惊讶地发现 Numpy 在 array_like 对象的定义上相当松散。基本上np.array(1) 是一个有效的numpy ndarray,形状为(),尺寸为0np.array([[1,2],[3]]) 也是一个有效的形状为(2,) 和维度为1 的ndarray。基本上np.array 挖掘尽可能多的维度,直到它达到非均匀性或零维值。这种实现可能非常快,但不一定安全。事实上,它非常容易出错。如果有人忘记了输入列表的一个元素,该函数不会返回任何错误,从而导致代码中出现其他最可能更令人困惑的错误。

我在想是否可以编写一个 checkArr 函数来检查多维列表的同质性和一致性,并且开销尽可能少。清理了其他一些 SO 帖子,我最终得到了这个递归解决方案:

def checkArr(A):
    assert isinstance(A, (list,tuple,range)), 
             "input must be iterable (list, tuple, range)"
    assert all(isinstance(a, type(A[0])) for a in A[1:]), 
             "elements of the input must of a the same type, input must be homogeneous"
    if isinstance(A[0], (list,tuple,range)):
        assert all(len(a)==len(A[0]) for a in A[1:]),
             "elements of the input must of a the same size, input must be uniform"
        [checkArr(a) for a in A]

现在我的问题是,这是否是最快的解决方案,还是可能实现更高性能/Pythonic?

【问题讨论】:

    标签: python list numpy multidimensional-array


    【解决方案1】:

    在创建数组时指定dtype argument 可避免从锯齿状矩阵无意中创建对象数组,而无需编写任何额外代码。

    np.array([[1, 2], [3, 4]], dtype=int)  # okay
    np.array([[1, 2], [3]], dtype=int)     # ValueError
    np.array([[1, "b"]], dtype=int)        # ValueError
    

    (关于最后一个,np.array([1, "b"]) 会在未设置数据类型的情况下默默地将“1”转换为字符串。)

    【讨论】:

      【解决方案2】:

      Python 说,请求宽恕比请求许可更容易。因此,如果您只调用np.array 然后检查object dtype,开销可能会更少。

      您需要注意的另一件事是它何时引发错误。例如:

      In [273]: np.array((np.zeros((2,3)), np.ones((2,4))))
      ---------------------------------------------------------------------------
      ValueError                                Traceback (most recent call last)
      <ipython-input-273-70f6273e3371> in <module>()
      ----> 1 np.array((np.zeros((2,3)), np.ones((2,4))))
      
      ValueError: could not broadcast input array from shape (2,3) into shape (2)
      

      如果非均匀性在第一维,它会产生一个对象 dtype 数组,例如np.array((np.zeros((2,3)), np.ones((1,4))))。但是当它处于更深层次时,它似乎分配了结果数组,然后将一个或多个组件数组复制到它时出现问题。这是一个难以诊断的案例。

      或者考虑:

      In [277]: np.array([[1,2,3],[4,5,'6']])
      Out[277]: 
      array([['1', '2', '3'],
             ['4', '5', '6']], dtype='<U21')
      

      嵌套列表中的最后一个元素强制使用字符串 dtype。如果最后一个元素是其他 PYthon 对象,我们可能是对象 dtype:

      In [279]: np.array([[1,2,3],[4,5,{}]])
      Out[279]: 
      array([[1, 2, 3],
             [4, 5, {}]], dtype=object)
      

      但是如果对象是一个列表,我们会得到一个关于广播错误的变体:

      In [280]: np.array([[1,2,3],[4,5,['6']]])
      ValueError: setting an array element with a sequence
      

      但如果您确实想先检查,np.stack 可能是一个不错的模型。如果给定数组或列表,axis=0 的行为类似于 np.array

      【讨论】:

        猜你喜欢
        • 2013-04-05
        • 2020-08-03
        • 1970-01-01
        • 2014-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-20
        • 2011-02-19
        相关资源
        最近更新 更多