2011-05-05 85 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, 
    )