重复二维数组的行

3
我有一个numpy数组,我想重复它n次,并保留行的原始顺序:
>>>a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

期望的输出(当n = 2时):
>>>a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

我找到了一个np.repeat函数,但是它不能保留列的原始顺序。是否有其他内置函数或技巧可以在保留顺序的同时重复数组?
6个回答

2
使用 np.repeat 然后再使用 np.concatenate:最初的回答
np.concatenate(np.repeat(a[None, :], n, axis=0), axis=0)

array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

另一个选择是使用 np.broadcast_to
np.broadcast_to(a, (n, *a.shape)).reshape(-1, a.shape[1])

array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

抱歉,我在期望的输出中犯了一个错误,它的维度是错误的。 - Alina
@Bazingaa 我不这么认为,它只会改变数组的步幅(数据不会改变)。 - cs95
@coldspeed:谢谢回复。使用timeit需要把东西放在一个函数里,对吧? - Sheldore
@coldspeed:请现在看一下,看我是否正确使用了timeit。感谢您的建议。 - Sheldore
@coldspeed:总的来说,你的第二个解决方案与我的相当。 - Sheldore
显示剩余3条评论

2
这是另一种做法。我还添加了一些时间比较,与@coldspeed的解决方案相比较。"最初的回答"
n = 2
a_new = np.tile(a.flatten(), n) 
a_new.reshape((n*a.shape[0], a.shape[1]))
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11],
#        [ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11]])

与coldspeed的解决方案性能比较

我的方法,当n = 10000时

最初的回答:

a = np.array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
n = 10000

def tile_flatten(a, n):
    a_new = np.tile(a.flatten(), n).reshape((n*a.shape[0], a.shape[1])) 
    return a_new

%timeit tile_flatten(a,n)
# 149 µs ± 20.2 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)   

coldspeed的第一种解决方案适用于n = 10000

a = np.array([[ 0,  1,  2,  3],
   [ 4,  5,  6,  7],
   [ 8,  9, 10, 11]])
n = 10000

def concatenate_repeat(a, n):
    a_new =  np.concatenate(np.repeat(a[None, :], n, axis=0), axis=0)
    return a_new

%timeit concatenate_repeat(a,n)
# 7.61 ms ± 1.37 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

coldspeed的第二个解决方案适用于n = 10000。

a = np.array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
n = 10000

def broadcast_reshape(a, n):
    a_new =  np.broadcast_to(a, (n, *a.shape)).reshape(-1, a.shape[1])
    return a_new

%timeit broadcast_reshape(a,n)
# 162 µs ± 29.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

@user2357112的解决方案

最初的回答
def tile_only(a, n):
    a_new = np.tile(a, (n, 1))
    return a_new

%timeit tile_only(a,n)
# 142 µs ± 21.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

1
在你测试我的答案时,元组应该是(n, 1)而不是(2, 1) - user2357112
@user2357112:哦,是的,谢谢你注意到了。我很惊讶看到数量级的差异。现在我已经纠正了它。 - Sheldore

2

numpy.repeat 是用于对单个元素进行重复的。如果要对整个数组进行重复,您需要使用numpy.tile

最初的回答
numpy.tile(a, (2, 1))

元组是每个轴上的重复次数。您希望第一个轴中有2个,第二个轴中有1个,因此元组为(2, 1),表示第一个轴上重复2次,第二个轴上重复1次。"Original Answer"翻译成"最初的回答"。

我想将您解决方案的时间表添加到我的答案中,以完整地突显您答案的新颖性。我可以这样做吗? - Sheldore
@Bazingaa:请继续。 - user2357112
我已经添加了。非常感谢。 - Sheldore

1

这是一个情况,np.resize 的填充模式非常有用:

In [82]: arr = np.arange(12).reshape(3,4)
In [83]: np.resize(arr,(6,4))
Out[83]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

resize 方法不同。)

0

你可以尝试使用numpy.tile()

这是如何使用numpy.tile重复数组并保存原始顺序的方法:

import numpy as np

a = np.array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

n = 5
b = np.tile(a, (n,1))
print b

输出:

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]] 

0

你也可以尝试一下

b=np.append(a,a).reshape(np.shape(a)[0]*2,np.shape(a)[1])

输出

array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接