一批移位范围的Numpy数组

3htmauhk  于 2023-11-18  发布在  其他
关注(0)|答案(3)|浏览(156)

我想创建一个numpy数组,填充来自另一个数组的值,但每行移动1(或其他常数)。例如,将元素为1,2,3,4,5.的数组Map到5x5数组,我会期望:
目前我只是在原始数组上运行一个循环,如下所示:

for batch in range(len(foo)-batch_size):
    result[batch,:] = foo[batch:batch+batch_size]

字符串
但我怀疑在numpy中有更好、更有效的方法吗?

twh00eeo

twh00eeo1#

您正在寻找sliding_window_view

a=np.arange(1,10)
np.lib.stride_tricks.sliding_window_view(a, 5)

字符串

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


编辑(约copy
你有两个相同的答案,相隔几秒钟:D(当我看到来自mozway的评论时,我应该知道答案即将到来)。
只有一句话:唯一的细微差别是mozway添加了copy()。他是对的:严格地说,需要执行与您的代码(for循环)等效的copy。因为sliding_window_view,正如其名称所示,不提供新数组,只是旧数组的视图。
因此,如果你稍后修改a,它也会修改输出数组。或者,如果相反,你修改输出数组的内容,它也会修改a
也就是说,如果您的代码提供了数据的新副本这一事实只是一个副作用,并且如果拥有此视图并不是真正的问题,(因为你没有意图修改a,或者修改输出数组的内容。或者因为你不关心a之后发生了什么,...),那么,作为一个视图是一个巨大的优势。因为这意味着没有数据被移动或复制(除了几个字节的元数据)。
因此,即使a包含数十亿个数字,sliding_window_view也是瞬时的。因为它所要做的就是调整元数据(形状和步幅)。而复制不会是瞬时的。
所以,你的问题的正确答案是mozway的:要在python中做你要做的事情,你需要copy。但是如果不需要的话,你可以考虑不做拷贝,因为如果数组很大,那会改变很多cpu。

s6fujrry

s6fujrry2#

假设一个1->9的数组作为输入,你可以使用numpy.lib.stride_tricks.sliding_window_view

from numpy.lib.stride_tricks import sliding_window_view as swv

a = np.arange(1, 10)

N = 5

out = swv(a, N).copy()

字符串
如果你有一个任意大的输入,并希望输出一个已知的大小:

a = np.arange(1, 100)

C = 5  # cols
R = 5  # rows

out = swv(a[:C+(R-1)], C).copy()


输出量:

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

rxztt3cl

rxztt3cl3#

使用np.broadcast_tonumpy broadcasting的另一种方法:

a = np.array([1, 2, 3, 4, 5])

out = np.broadcast_to(a, (a.shape[0], a.shape[0])) + np.arange(a.shape[0])[:, None]

字符串
输出量:

>>> out
array([[1, 2, 3, 4, 5],
       [2, 3, 4, 5, 6],
       [3, 4, 5, 6, 7],
       [4, 5, 6, 7, 8],
       [5, 6, 7, 8, 9]])

相关问题