扩展4D numpy数组维度的最有效方法是什么?

时间:2014-11-25 22:15:28

标签: arrays numpy multidimensional-array

例如,假设我有一个形状数组(2,3,4,5),我想在其中添加一个(2,3,4,1)数组以生成一个形状数组(2 -1,3,4,6-)。

最有效的方法是什么(大尺寸)?

有没有比dimshuffle和vstack / hstack / dstack更好的东西?

(Python 2.7)

2 个答案:

答案 0 :(得分:1)

以下是执行此操作的各种方法,并附带基准:

a = np.zeros([100,200,300,5])
b = np.zeros([100,200,300,1])

%timeit c=np.concatenate([a,b],-1)
#1 loops, best of 3: 241 ms per loop

%timeit c=np.vstack([a.T,b.T]).T
#1 loops, best of 3: 309 ms per loop

%timeit c=np.empty([100,200,300,5]); c[...,:5]=a; c[...,5:]=b
#1 loops, best of 3: 311 ms per loop

# Assuming c was already allocated:
%timeit c[...,:5]=a; c[...,5:]=b
#10 loops, best of 3: 113 ms per loop

这些时间都很可比,而且都非常慢。如果所有数组都处于转置顺序,我们可以做得更好:

va = np.zeros([5,300,200,100])
vb = np.zeros([1,300,200,100])

%timeit vc=np.concatenate([va,vb],0)
#1 loops, best of 3: 191 ms per loop

%timeit vc=np.vstack([va,vb])
#1 loops, best of 3: 284 ms per loop

%timeit vc=np.empty([6,300,200,100]); vc[:5]=va; vc[5:]=vb
#1 loops, best of 3: 281 ms per loop

#Assuming vc is already allocated. This case is somehow
#much faster than the others!
%timeit vc[:5]=va; vc[5:]=vb
#10 loops, best of 3: 26.4 ms per loop

#Somehow the time for allocating vc and for copying the
#values does not add up. I guess this has to do with
#caching working better when the same buffer is reused
%timeit vc=np.empty([6,300,200,100])
#100000 loops, best of 3: 7.73 µs per loop

在fortran中实现相同的操作并通过f2py调用它产生大约55 ms的时间,仅用于未转置的情况。因此,似乎这些选项都不是非常低效。我建议np.concatenate。由于某种原因,它是通用的,并且比同等的*stack略快。也就是说,除非你可以预先分配和重用输出数组,在这种情况下,使用broadcasing进行分配的速度至少要快2倍。

答案 1 :(得分:0)

使用arr.resize(new_shape=(2,3,4,6))。这将尝试重新分配原始数组使用的现有内存,因此它可能比保证返回新分配的数组的任何其他方法更快。

缺点是它不可能一直就地执行此操作,在这种情况下,您别无选择,只能创建一个新阵列,例如:使用numpy.append

进一步了解resize和一些警告here