如何在不复制数据的情况下重复NumPy数组?

25

我想创建一个1D NumPy数组,其由另一个1D数组的1000个相邻重复组成,而不是复制数据1000次。

这是否可能?

如果有帮助的话,我打算将两个数组都视为不可变。


2
我在尝试搜索Python中的大数据操作时发现了这个问题。我读到了有关步幅的信息,并想知道为什么需要复制本质上相同的数据(指向内存中相同的数据)。你不能从单个数据集中读取两次吗?我只是想知道为什么要进行这种复制。谢谢。 - user201788
我觉得很多时候你可能想要做这个,但真正想做的是使用广播。 - endolith
5个回答

28

你不能这样做;一个 NumPy 数组必须沿着每个维度具有一致的步幅,而你的步长大部分时间都需要朝着一个方向前进,但有时会往后跳。

最接近的解决方案是创建一个 1000 行的二维数组,其中每一行都是你第一个数组的视图,或者使用 flatiter 对象,该对象的行为类似于一个一维数组。flatiters 支持迭代和索引,但是你无法对它们进行视图操作;所有的索引都会创建一个副本。

设置:

import numpy as np
a = np.arange(10)

2D 视图:

b = np.lib.stride_tricks.as_strided(a, (1000, a.size), (0, a.itemsize))

迭代器对象:

c = b.flat

很酷,我在想是否可以使用步幅,但是我不知道该怎么做!是b.flat还是b.flatten() - Benjamin
2
b.flat.base is b 是 True;b.flatten().base is b 是 False,所以你需要使用 b.flat - JoshAdel
不确定那是什么意思。 b.flatten().base 没有返回值… (b.flat == b.flatten()).all() 为 True,那有什么区别? - Benjamin
请查看http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.base.html。不同之处在于您的比较是基于逐个元素的值是否相同。`.base`告诉您有关数据所有权的信息。 - JoshAdel
@JoshAdel:谢谢,这很有用。 - Benjamin

19
broadcast_to是自numpy 1.10版本开始提供的函数,它可以让你以更少的努力有效地重复一个数组。以下内容为接受答案的风格:
import numpy as np
arr = np.arange(10)
repeated = np.broadcast_to(arr, (1000, arr.size))

2

我不完全确定你所说的“不要复制1000次数据”的意思。如果您正在寻找一种numpy方法,可以一次性地从a构建b(而不是循环),您可以使用以下方法:

a = np.arange(1000)
b = np.tile(a,1000)

否则,我会做类似以下的事情:
a = np.arange(1000)
ii = [700,2000,10000] # The indices you want of the tiled array
b = a[np.mod(ii,a.size)]

在这种情况下,由于使用了花式索引(它会创建一个副本),b不是a的视图,但至少它返回一个numpy数组,并且不会在内存中创建1000x1000x1的数组,只包含您想要的元素。
就其是否不可变(参见不可变numpy数组?),您需要为每个单独切换标志,因为副本不保留标志设置。

0

我并不声称这是最优雅的解决方案,因为你必须欺骗numpy创建一个对象数组(请参见带有注释的行)

from numpy import array

n = 3

a = array([1,2])
a.setflags(write=False)
t = [a]*n + [array([1])] # Append spurious array that is not len(a)
r = array(t,dtype=object)
r.setflags(write=False)

assert id(a) == id(t[1]) == id(r[1])

-1
这个可以吗:
import numpy
a = numpy.array([1, 2, 3, 4])
b = numpy.ones((1000, a.shape[0]))
b *= a
b = b.flatten()

2
如果你要生产副本,这种做法似乎非常昂贵,并且比只使用“np.tile”慢约15倍。 - JoshAdel

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