2011-05-05 1128 views
129

我需要创建一个长度为n的NumPy数组,其中每个元素是vNumPy数组初始化(填充相同的值)

有什么优于:

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

我知道zerosones会为V = 0,1,我可以用v * ones(n)工作,但是当vNone它不会工作,并且也将慢得多。

+1

在我的电脑,对于0的情况下,使用一个'= np.zeros(n)的'在环路是比'更快。填充(0)'。这与我所期望的相反,因为我认为'a = np.zeros(n)'需要分配和初始化新的内存。如果有人能解释这一点,我将不胜感激。 – user3731622 2016-09-27 23:40:03

回答

148

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()方法对我来说很好,但我找不到一点文档。任何人都可以将我指向正确的地方吗? – 2014-01-17 16:39:07

+0

您至少可以在Python shell中执行'help(numpy.full)'。我也很惊讶它不在网络文档中。 – EOL 2014-01-22 13:49:26

+0

在我的系统上(Python 2.7,Numpy 1.8),np.full()实际上比np.empty()跟np.fill()稍慢。 – 2014-07-25 08:37:06

54

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

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

你应该总是避免迭代,就像你在你的例子中做的那样。一个简单的a[:] = v将完成你的迭代使用numpy broadcasting

+1

谢谢。在看“填充”时,我看到“重复”更适合我的需求。 – max 2011-05-05 00:57:57

+0

你介意更新你的答案,说你对'a [:] = v'的推荐实际上比'fill'更快吗? – max 2012-10-24 21:21:48

+0

@max更快吗?广播是填充数组的一种更通用的方式,我猜测它会慢或等于'fill'这个非常狭窄的用例。 – Paul 2012-10-24 22:52:50

5

您可以使用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意指“瓦片”的阵列(而不是标量,如在这种情况下),它会做的工作,在创建任何大小和尺寸的预填充阵列。

76

更新了numpy的1.7.0:(HAT-尖端@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 
+10

添加更新和直接'np.full()'的时间将是有用的。在我的机器上,使用NumPy 1.8.1,它比不太直接的'fill()'版本慢了大约15%(这是意想不到的,因为full()有可能会稍微快一点)。 – EOL 2014-05-14 06:44:09

+0

@DavidSanders:我不确定我在跟着你:'fill()'是最快的解决方案。乘法解决方案要慢得多。 – EOL 2015-06-23 03:22:49

+2

注意:如果速度真的是一个问题,使用'10000'而不是'1e4'的大小会产生明显的差异,出于某种原因('full()'比'1e4'慢50%)。 – EOL 2015-06-23 03:27:19

13

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

所以,尽量找出来,用什么速度最快的平台上。

6

我脑子里

numpy.array(n * [value]) 

,但显然这是比所有其他的建议较慢足够大n

这里是与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(23)], 
    xlabel='len(a)', 
    logx=True, 
    logy=True, 
    )