初始化一个numpy数组。

185
有没有一种方法可以初始化一个numpy数组的形状并向其中添加元素?我将用列表示例来解释我需要的内容。如果我想创建一个在循环中生成的对象列表,我可以这样做:
a = []
for i in range(5):
    a.append(i)

我想使用一个numpy数组来做类似的事情。我知道vstack、concatenate等函数,但是它们似乎需要两个numpy数组作为输入。我需要的是:

big_array # Initially empty. This is where I don't know what to specify
for i in range(5):
    array i of shape = (2,4) created.
    add to big_array
big_array 应该有一个形状为 (10,4)。如何实现?

编辑:

我想澄清一下。我知道可以定义 big_array = numpy.zeros((10,4)) 然后填充它。但是,这需要预先指定 big_array 的大小。虽然我知道在这种情况下的大小,但如果不知道大小会怎样?当我们使用 .append 函数扩展 python 中的列表时,我们不需要预先知道其最终大小。我想知道是否存在类似的方法,从空数组开始创建更大的数组以及如何从小数组构造大数组。


顺便提一下,你的第一个代码示例可以被写成一个简洁明了的列表推导式:[i for i in range(5)]。(等价于 list(range(5)),尽管这只是一个人为的例子。) - Katriel
1
你用了什么解决方案?我试图做类似于 x = numpy.array() 的事情,就像我们对列表做的那样 y = [],但它没有起作用。 - kRazzy R
我在想是否存在一种类似的方法,可以通过从较小的数组开始,创建一个更大的数组。根据被接受的答案,我不明白为什么较小的数组对于这个任务有帮助。如果确实有一个不同的问题,似乎大家都没有注意到。 - undefined
14个回答

214

numpy.zeros

返回一个给定形状和数据类型的新数组,用零填充。

或者

numpy.ones

返回一个给定形状和数据类型的新数组,用1填充。

或者

numpy.empty

返回一个给定形状和数据类型的新数组,但不初始化元素。


然而,在numpy中我们构建数组的心态并不像将元素附加到列表中那样多用,因为它不太有效(numpy数据类型更接近底层的C数组)。 相反,您应该预先分配所需大小的数组,然后填充行。 如果必须,可以使用numpy.append,但效率较低。


2
我知道我可以设置big_array = numpy.zeros,然后用创建的小数组填充它。但是,这需要我提前指定big_array的大小。是否有像列表函数的.append一样的东西,我不需要提前指定大小。谢谢! - Curious2learn
2
@Curious2learn。不,Numpy中没有类似于“append”的功能。虽然有一些函数可以通过创建新的数组来连接或堆叠已有数组,但它们并不是通过“append”来实现的。这是因为数据结构的设置方式不同。Numpy数组的快速性是由于能够更紧凑地存储值,但需要具有固定的大小才能获得此速度。Python列表则旨在以牺牲速度和大小为代价提供更灵活的设计。 - Justin Peel
3
@Curious:numpy 中确实有一个“append”函数,只不过如果没有预先分配空间的话效率会比较低(在这种情况下,由于每次“append”都会复制整个数组,因此效率要低得多),所以它不是标准技术。 - Katriel
1
如果仅使用值填充了np.empty数组的一部分,那么剩余的“空”项怎么办? - wsdzbm
1
如果你只知道宽度(例如np.concatenate()所需的宽度),你可以使用以下方式进行初始化:np.empty((0, some_width))。这样第一个数组就不会是垃圾值了。 - NumesSanguis
1
至少在我尝试时,np.empty并不是真正的空,而是保存了一些值,我猜这些值是分配给数组的内存空间中的任何内容。 - Yoav Vollansky

52

我通常的做法是创建一个普通的列表,然后将我的内容添加到其中,最后将列表转换为NumPy数组,如下所示:

import numpy as np
big_array = [] #  empty regular list
for i in range(5):
    arr = i*np.ones((2,4)) # for instance
    big_array.append(arr)
big_np_array = np.array(big_array)  # transformed to a numpy array

当然,在创建阶段,你的最终对象需要占用两倍的内存空间,但在Python列表上进行附加非常快,并且使用np.array()创建也很快。


16
如果你事先知道数组的大小,这不是正确的方法,然而……当我不知道数组最终会有多大时,我经常使用这种方法。例如,从文件或另一个进程中读取数据时。实际上,这并不像一开始看起来那么糟糕,因为Python和NumPy非常聪明。 - travc

34

numpy 1.8中引入了以下函数:

numpy.full

返回一个指定形状和类型、以fill_value填充的新数组。

示例:

>>> import numpy as np
>>> np.full((2, 2), np.inf)
array([[ inf,  inf],
       [ inf,  inf]])
>>> np.full((2, 2), 10)
array([[10, 10],
       [10, 10]])

17

Python的数组类比

a = []
for i in range(5):
    a.append(i)

这是:

import numpy as np

a = np.empty((0))
for i in range(5):
    a = np.append(a, i)

5
empty((0))会初始化一个NumPy数组。 - Adobe
3
np.empty((0))中的括号是多余的。 - Szymon Roziewski

8
为了使用特定的矩阵初始化一个numpy数组:
import numpy as np

mat = np.array([[1, 1, 0, 0, 0],
                [0, 1, 0, 0, 1],
                [1, 0, 0, 1, 1],
                [0, 0, 0, 0, 0],
                [1, 0, 1, 0, 1]])

print mat.shape
print mat

输出:

(5, 5)
[[1 1 0 0 0]
 [0 1 0 0 1]
 [1 0 0 1 1]
 [0 0 0 0 0]
 [1 0 1 0 1]]

8
在进行数组计算时,尽可能避免使用显式循环,因为这会减少该形式计算的速度增益。有多种方法可以初始化numpy数组。如果您想用零填充它,请像katrielalex所说的那样做: big_array = numpy.zeros((10,4)) 编辑:您要创建什么样的序列?您应该查看不同的numpy函数来创建数组,例如numpy.linspace(start, stop, size)(等间距数字)或numpy.arange(start, stop, inc)。在可能的情况下,这些函数将比使用显式循环执行相同工作的速度更快。

7

对于你的第一个数组示例,使用以下代码:

a = numpy.arange(5)

要初始化 big_array,使用:

big_array = numpy.zeros((10,4))

假设您想用零进行初始化,这是非常典型的情况,但是在numpy中有许多其他初始化数组的方法

编辑: 如果您不知道big_array的大小,请先使用append构建Python列表,当您收集到列表中的所有内容时,使用numpy.array(mylist)将此列表转换为numpy数组。原因是列表旨在高效快速地增长,而numpy.concatenate会非常低效,因为numpy数组不容易改变大小。但是,一旦收集了所有内容并且知道最终的数组大小,就可以有效地构建numpy数组。


7

numpy.fromiter() 是您要寻找的函数:

big_array = numpy.fromiter(xrange(5), dtype="int")

它还可以与生成器表达式一起使用,例如:
big_array = numpy.fromiter( (i*(i+1)/2 for i in xrange(5)), dtype="int" )

如果您提前知道数组的长度,可以使用可选的 "count" 参数来指定它。


3
我现在运行了 timeit,发现 np.fromiter() 可能比 np.array() 慢。下面是我的代码和结果: timeit("np.array(i for i in xrange(100))", setup="import numpy as np", number = 10000) -> 0.02539992332458496, 而 timeit("np.fromiter((i for i in xrange(100)), dtype=int)", setup="import numpy as np", number = 10000) 的结果是 -> 0.13351011276245117。 - hlin117

4

我知道这有点晚了,但我没有注意到其他答案中提到过对空数组进行索引:

big_array = numpy.empty(10, 4)
for i in range(5):
    array_i = numpy.random.random(2, 4)
    big_array[2 * i:2 * (i + 1), :] = array_i

这样做,你可以使用numpy.empty预先分配整个结果数组,并使用索引赋值逐行填充。
在你提供的示例中,使用empty而不是zeros进行预分配是完全安全的,因为你保证整个数组将被生成的块所填满。

3

首先建议定义形状。 然后迭代它以插入值。

big_array= np.zeros(shape = ( 6, 2 ))
for it in range(6):
    big_array[it] = (it,it) # For example

>>>big_array

array([[ 0.,  0.],
       [ 1.,  1.],
       [ 2.,  2.],
       [ 3.,  3.],
       [ 4.,  4.],
       [ 5.,  5.]])

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