NumPy:数组和标量列表中的2D数组

时间:2016-02-06 17:49:26

标签: python arrays numpy scalar

我需要从1D数组和标量列表中创建2D numpy数组,以便复制标量以匹配1D数组的长度。

所需行为的示例

>>> x = np.ones(5)
>>> something([x, 0, x])
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  1.,  1.]])

我知道列表中的矢量元素总是具有相同的长度(形状),所以我可以通过做这样的事情来“手动”完成:

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中,或者如果没有,是否有比上面更好的解决方案(例如,更一般,更可靠,更快)。< / p>

3 个答案:

答案 0 :(得分:3)

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.broadcastnp.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.broadcastnp.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])返回:

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)

答案 1 :(得分:1)

一种较短的方式,但我怀疑是否更快:

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))

答案 2 :(得分:0)

对于25行,private SingletonObject() { //optional code } 的列表理解版本速度介于somethingbroadcase之间:

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

对于2d 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 x理解上的vstack可能是唯一正确的理解:

if