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


237

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

还有什么比:

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

我知道zeros并且ones可以在v = 0,1下使用。我可以使用v * ones(n),但是vis 上将不起作用None,而且速度会慢很多。


1
在我的计算机上,对于0情况,a = np.zeros(n)在循环中使用的速度比快a.fill(0)。这与我的预期相反,因为我认为a=np.zeros(n)需要分配和初始化新的内存。如果有人能解释这一点,我将不胜感激。
user3731622

您不能将None放在一个numpy数组中,因为单元格是使用特定的数据类型创建的,而None具有它自己的类型并且实际上是一个指针。
卡米恩

@Camion是的,我现在知道:)当然v * ones(n)仍然很恐怖,因为它使用了昂贵的乘法。尽管将其替换为*+v + zeros(n)在某些情况下却表现出令人惊讶的良好效果(stackoverflow.com/questions/5891410/…)。
最多

最大值,而不是在添加v之前创建零数组,更快地将其创建为空,var = np.empty(n)然后用'var [:] = v'填充。(顺便说一句,np.full()就是这样快)
Camion

Answers:


308

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]])

可以说这是创建一个填充有某些值的数组方法,因为它明确描述了要实现的目标(并且从原理上讲,它可以执行非常具体的任务,因此非常高效)。


1
这个full()方法对我来说效果很好,但是我找不到关于它的文档。谁能指出我在正确的地方?
James Adams

1
您至少可以help(numpy.full)在Python Shell中进行操作。我也很惊讶它不在Web文档中。
Eric O Lebigot

在我的系统(Python 2.7,Numpy 1.8)上,np.full()实际上比np.empty()稍慢,其次是np.fill()。
约翰·兹温克

1
对于10,000个元素,我观察到相同的东西(除了np.fill()不存在,应该是arr.fill()),相差约10%。如果差异更大,我会在NumPy错误跟踪器中提出一个问题。:)我更喜欢更明确,更清晰的代码,因为执行时间差异很小,所以我会一直坚持下去np.full()
Eric O Lebigot

在我的机器np.full()是相同的速度np.array.fill()
Fnord

92

已为Numpy 1.7.0更新:(@ Rolf Bartstra的提示)。

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

以降序排列:

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

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

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

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

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

13
为最近的和直接的添加时间np.full()将是有用的。在我的计算机上,使用NumPy 1.8.1时,它比不那么直接的fill()版本慢15%(这出乎意料,因为full()它的运行速度可能会稍快)。
Eric O Lebigot 2014年

@DavidSanders:我不确定我是否关注您:这fill()是最快的解决方案。乘法解决方案要慢得多。
Eric O Lebigot

2
注意:如果确实要考虑速度,则出于某种原因(使用时,速度慢将近50%),使用size 10000代替1e4会产生明显的差异。full()1e4
Eric O Lebigot

仅将我的结果添加到full(),当数据类型不是显式为float时,它的运行速度就会大大降低。否则,可以与此处的最佳方法相媲美(但速度稍慢)。
user2699 '16

@ user2699我不遵守这一点,10万组的元素:full(100000, 5)full(100000, 5, dtype=float)full(100000, 5, dtype=int)a =np.empty(100000); a.fill(5)所有的花费大约在同一时间在我的机器上(不带缓存:%timeit -r1 -n1 …)(NumPy的1.11.2)。
Eric O Lebigot

65

我相信这fill是最快的方法。

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

您还应该始终避免像在示例中那样进行迭代。一个简单的a[:] = v函数将使用numpy 广播来完成您的迭代操作。


1
谢谢。通过查看fill,我发现它更repeat适合我的需求。
最大

您介意更新您的回答,说您的建议a[:]=v实际上比总体上更快fill吗?
最大

@max更快吗?广播是填充数组的更一般的方法,我猜是慢了或等于狭义的用例fill
保罗

16

显然,不仅绝对速度而且速度顺序(如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!)

因此,请尝试找出并使用平台上最快的功能。


14

我有

numpy.array(n * [value])

请记住,但是显然,这比所有其他建议都足够慢n

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

在此处输入图片说明

这两种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,
)

7

您可以使用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是为了“平铺”一个数组(而不是这种情况下的标量),但它可以完成工作,创建任何大小和尺寸的预填充数组。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.