在我的other question之后,我惊讶地发现Numpy在array_like对象的定义上非常宽松。基本上np.array(1)
是形状为()
且尺寸为0
的有效numpy ndarray! np.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]
现在我的问题是这是否是最快的解决方案,还是可能实现更高性能/ Python的实现?
答案 0 :(得分: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”转换为字符串。)
答案 1 :(得分:1)
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
。