NumPy:来自数组和标量列表的二维数组
NumPy: 2D array from a list of arrays and scalars
我需要从一维数组和标量列表创建一个二维 numpy 数组,以便复制标量以匹配一维数组的长度。
所需行为示例
>>> x = np.ones(5)
>>> something([x, 0, x])
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
我知道列表的矢量元素总是具有相同的长度(形状),所以我可以通过这样做 "by hand" 来做到这一点:
def something(lst):
for e in lst:
if isinstance(e, np.ndarray):
l = len(e)
break
tmp = []
for e in lst:
if isinstance(e, np.ndarray):
tmp.append(e)
l = len(e)
else:
tmp.append(np.empty(l))
tmp[-1][:] = e
return np.array(tmp)
我想问的是在 numpy 的某个地方是否隐藏了一些现成的解决方案,或者如果有 none,是否有更好的(例如更通用、更可靠、更快)的解决方案比上面那个。
更短的方式,但我怀疑是否更快:
l = len(max(lst, key=lambda e: len(e) if isinstance(e, np.ndarray) else 0))
new_lst = np.array([(x if isinstance(x, np.ndarray) else np.ones(l) * x) for x in lst])
编辑:使用 np.fromiter
更快:
l = len(max(lst, key=lambda e: len(e) if isinstance(e, np.ndarray) else 0))
new_lst = np.fromiter(((x if isinstance(x, np.ndarray) else np.ones(l) * x) for x in lst))
并使用 while 循环来更快地完成它,但代码有点长:
i = 0
while not isinstance(lst[i], np.ndarray):
i += 1
l = len(lst[i])
new_lst = np.fromiter(((x if isinstance(x, np.ndarray) else np.ones(l) * x) for x in lst))
In [179]: np.column_stack(np.broadcast(x, 0, x))
Out[179]:
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
或
In [187]: np.row_stack(np.broadcast_arrays(x, 0, x))
Out[187]:
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
使用 np.broadcast
比 np.broadcast_arrays
快:
In [195]: %timeit np.column_stack(np.broadcast(*[x, 0, x]*10))
10000 loops, best of 3: 46.4 µs per loop
In [196]: %timeit np.row_stack(np.broadcast_arrays(*[x, 0, x]*10))
1000 loops, best of 3: 380 µs per loop
但比您的 something
函数慢:
In [201]: %timeit something([x, 0, x]*10)
10000 loops, best of 3: 37.3 µs per loop
注意np.broadcast
最多可以传32个数组:
In [199]: np.column_stack(np.broadcast(*[x, 0, x]*100))
ValueError: Need at least two and fewer than (32) array objects.
而 np.broadcast_arrays
是无限的:
In [198]: np.row_stack(np.broadcast_arrays(*[x, 0, x]*100))
Out[198]:
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.],
...,
[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
使用 np.broadcast
或 np.broadcast_arrays
比
something
。它适用于不同(但可广播)形状的阵列,例如
实例:
In [209]: np.column_stack(np.broadcast(*[np.atleast_2d(x), 0, x]))
Out[209]:
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
而 something([np.atleast_2d(x), 0, x])
returns:
In [211]: something([np.atleast_2d(x), 0, x])
Out[211]:
array([array([[ 1., 1., 1., 1., 1.]]), array([ 0.]),
array([ 1., 1., 1., 1., 1.])], dtype=object)
对于 25 行,something
的列表理解版本在速度上介于 broadcase
和 broadcast_arrays
之间:
In [48]: ll=[x,0,x,x,0]*5
In [49]: np.vstack([y if isinstance(y,np.ndarray) else np.zeros(5) for y in ll]).shape
Out[49]: (25, 5)
In [50]: timeit np.vstack([y if isinstance(y,np.ndarray) else np.zeros(5) for y in ll]).shape
1000 loops, best of 3: 219 us per loop
In [51]: timeit np.vstack(np.broadcast_arrays(*ll))
1000 loops, best of 3: 790 us per loop
In [52]: timeit np.column_stack(np.broadcast(*ll)).shape
10000 loops, best of 3: 126 us per loop
使用 np.array
而不是 vstack
它会变得更好:
In [54]: timeit np.array([y if isinstance(y,np.ndarray) else np.zeros(5) for y in ll]).shape
10000 loops, best of 3: 54.2 us per loop
对于2dx
,if
上的vstack
理解可能是唯一正确的:
In [66]: x=np.arange(10).reshape(2,5)
In [67]: ll=[x,0,x,x,0]
In [68]: np.vstack([y if isinstance(y,np.ndarray) else np.zeros(5) for y in ll])
Out[68]:
array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 0., 0., 0., 0., 0.],
[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 0., 0., 0., 0., 0.]])
我需要从一维数组和标量列表创建一个二维 numpy 数组,以便复制标量以匹配一维数组的长度。
所需行为示例
>>> x = np.ones(5)
>>> something([x, 0, x])
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
我知道列表的矢量元素总是具有相同的长度(形状),所以我可以通过这样做 "by hand" 来做到这一点:
def something(lst):
for e in lst:
if isinstance(e, np.ndarray):
l = len(e)
break
tmp = []
for e in lst:
if isinstance(e, np.ndarray):
tmp.append(e)
l = len(e)
else:
tmp.append(np.empty(l))
tmp[-1][:] = e
return np.array(tmp)
我想问的是在 numpy 的某个地方是否隐藏了一些现成的解决方案,或者如果有 none,是否有更好的(例如更通用、更可靠、更快)的解决方案比上面那个。
更短的方式,但我怀疑是否更快:
l = len(max(lst, key=lambda e: len(e) if isinstance(e, np.ndarray) else 0))
new_lst = np.array([(x if isinstance(x, np.ndarray) else np.ones(l) * x) for x in lst])
编辑:使用 np.fromiter
更快:
l = len(max(lst, key=lambda e: len(e) if isinstance(e, np.ndarray) else 0))
new_lst = np.fromiter(((x if isinstance(x, np.ndarray) else np.ones(l) * x) for x in lst))
并使用 while 循环来更快地完成它,但代码有点长:
i = 0
while not isinstance(lst[i], np.ndarray):
i += 1
l = len(lst[i])
new_lst = np.fromiter(((x if isinstance(x, np.ndarray) else np.ones(l) * x) for x in lst))
In [179]: np.column_stack(np.broadcast(x, 0, x))
Out[179]:
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
或
In [187]: np.row_stack(np.broadcast_arrays(x, 0, x))
Out[187]:
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
使用 np.broadcast
比 np.broadcast_arrays
快:
In [195]: %timeit np.column_stack(np.broadcast(*[x, 0, x]*10))
10000 loops, best of 3: 46.4 µs per loop
In [196]: %timeit np.row_stack(np.broadcast_arrays(*[x, 0, x]*10))
1000 loops, best of 3: 380 µs per loop
但比您的 something
函数慢:
In [201]: %timeit something([x, 0, x]*10)
10000 loops, best of 3: 37.3 µs per loop
注意np.broadcast
最多可以传32个数组:
In [199]: np.column_stack(np.broadcast(*[x, 0, x]*100))
ValueError: Need at least two and fewer than (32) array objects.
而 np.broadcast_arrays
是无限的:
In [198]: np.row_stack(np.broadcast_arrays(*[x, 0, x]*100))
Out[198]:
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.],
...,
[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
使用 np.broadcast
或 np.broadcast_arrays
比
something
。它适用于不同(但可广播)形状的阵列,例如
实例:
In [209]: np.column_stack(np.broadcast(*[np.atleast_2d(x), 0, x]))
Out[209]:
array([[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 1.]])
而 something([np.atleast_2d(x), 0, x])
returns:
In [211]: something([np.atleast_2d(x), 0, x])
Out[211]:
array([array([[ 1., 1., 1., 1., 1.]]), array([ 0.]),
array([ 1., 1., 1., 1., 1.])], dtype=object)
对于 25 行,something
的列表理解版本在速度上介于 broadcase
和 broadcast_arrays
之间:
In [48]: ll=[x,0,x,x,0]*5
In [49]: np.vstack([y if isinstance(y,np.ndarray) else np.zeros(5) for y in ll]).shape
Out[49]: (25, 5)
In [50]: timeit np.vstack([y if isinstance(y,np.ndarray) else np.zeros(5) for y in ll]).shape
1000 loops, best of 3: 219 us per loop
In [51]: timeit np.vstack(np.broadcast_arrays(*ll))
1000 loops, best of 3: 790 us per loop
In [52]: timeit np.column_stack(np.broadcast(*ll)).shape
10000 loops, best of 3: 126 us per loop
使用 np.array
而不是 vstack
它会变得更好:
In [54]: timeit np.array([y if isinstance(y,np.ndarray) else np.zeros(5) for y in ll]).shape
10000 loops, best of 3: 54.2 us per loop
对于2dx
,if
上的vstack
理解可能是唯一正确的:
In [66]: x=np.arange(10).reshape(2,5)
In [67]: ll=[x,0,x,x,0]
In [68]: np.vstack([y if isinstance(y,np.ndarray) else np.zeros(5) for y in ll])
Out[68]:
array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 0., 0., 0., 0., 0.],
[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 0., 0., 0., 0., 0.]])