NumPy数组初始化(用相同的值填充)

我需要创建一个长度为n的NumPy数组,其中每个元素都是v

还有什么比:

a = empty(n)
for i in range(n):
a[i] = v

我知道zerosones适用于v = 0,1。我可以使用v * ones(n),但当__ABC3为None时,将不起作用,并且会慢得多。

564569 次浏览

我相信fill是最快的方法来做到这一点。

a = np.empty(10)
a.fill(7)

您还应该始终避免像您在示例中所做的那样进行迭代。一个简单的a[:] = v将完成你使用numpy 广播迭代所做的事情。

你可以使用numpy.tile,例如:

v = 7
rows = 3
cols = 5
a = numpy.tile(v, (rows,cols))
a
Out[1]:
array([[7, 7, 7, 7, 7],
[7, 7, 7, 7, 7],
[7, 7, 7, 7, 7]])

尽管tile意味着“平铺”一个数组(而不是在这种情况下的标量),它将完成工作,创建任何大小和维度的预填充数组。

为Numpy 1.7.0更新:(向@Rolf Bartstra致敬。)

a=np.empty(n); a.fill(5)最快。

按速度递减排列:

%timeit a=np.empty(10000); a.fill(5)
100000 loops, best of 3: 5.85 us per loop


%timeit a=np.empty(10000); a[:]=5
100000 loops, best of 3: 7.15 us per loop


%timeit a=np.ones(10000)*5
10000 loops, best of 3: 22.9 us per loop


%timeit a=np.repeat(5,(10000))
10000 loops, best of 3: 81.7 us per loop


%timeit a=np.tile(5,[10000])
10000 loops, best of 3: 82.9 us per loop

显然,不仅绝对速度,而且速度订单(由user1579844报告)都是依赖于机器的;以下是我的发现:

a=np.empty(1e4); a.fill(5)是最快的;

按速度递减排列:

timeit a=np.empty(1e4); a.fill(5)
# 100000 loops, best of 3: 10.2 us per loop
timeit a=np.empty(1e4); a[:]=5
# 100000 loops, best of 3: 16.9 us per loop
timeit a=np.ones(1e4)*5
# 100000 loops, best of 3: 32.2 us per loop
timeit a=np.tile(5,[1e4])
# 10000 loops, best of 3: 90.9 us per loop
timeit a=np.repeat(5,(1e4))
# 10000 loops, best of 3: 98.3 us per loop
timeit a=np.array([5]*int(1e4))
# 1000 loops, best of 3: 1.69 ms per loop (slowest BY FAR!)

所以,试着找出答案,并使用你平台上最快的方法。

NumPy 1.8引入了np.full(),这是一个比empty()后跟fill()更直接的方法,用于创建一个充满特定值的数组:

>>> np.full((3, 5), 7)
array([[ 7.,  7.,  7.,  7.,  7.],
[ 7.,  7.,  7.,  7.,  7.],
[ 7.,  7.,  7.,  7.,  7.]])


>>> np.full((3, 5), 7, dtype=int)
array([[7, 7, 7, 7, 7],
[7, 7, 7, 7, 7],
[7, 7, 7, 7, 7]])

这可以说是创建一个充满特定值的数组的方式,因为它显式地描述了要实现的内容(原则上它可以非常有效,因为它执行非常具体的任务)。

我心里有np.array(n * [value]),但显然,对于足够大的n,这比所有其他建议都要慢。在可读性和速度方面最好的是

np.full(n, 3.14)

这里是与perfplot(我的一个宠物项目)的完整比较。

enter image description here

两个empty替代品仍然是最快的(NumPy 1.12.1)。full适用于大型数组。


代码生成的情节:

import numpy as np
import perfplot




def empty_fill(n):
a = np.empty(n)
a.fill(3.14)
return a




def empty_colon(n):
a = np.empty(n)
a[:] = 3.14
return a




def ones_times(n):
return 3.14 * np.ones(n)




def repeat(n):
return np.repeat(3.14, (n))




def tile(n):
return np.repeat(3.14, [n])




def full(n):
return np.full((n), 3.14)




def list_to_array(n):
return np.array(n * [3.14])




perfplot.show(
setup=lambda n: n,
kernels=[empty_fill, empty_colon, ones_times, repeat, tile, full, list_to_array],
n_range=[2 ** k for k in range(27)],
xlabel="len(a)",
logx=True,
logy=True,
)

没有numpy

>>>[2]*3
[2, 2, 2]

你也可以使用np.broadcast_to

要创建一个形状(尺寸)s,值为v的数组,你可以这样做(在你的例子中,数组是1-D,并且s = (n,)):

a = np.broadcast_to(v, s).copy()

如果a只需要是只读的,你可以使用以下方法(这更有效):

a = np.broadcast_to(v, s)

这样做的好处是v可以作为单个数字给出,但如果需要不同的值,也可以作为数组给出(只要v.shape匹配s的尾部)。

如果你想强制创建数组的dtype:

a = np.broadcast_to(np.asarray(v, dtype), s).copy()

我们也可以写成

v=7
n=5
a=np.linspace(v,v,n)