NumPy 数组初始化(填充相同的值)
Posted
技术标签:
【中文标题】NumPy 数组初始化(填充相同的值)【英文标题】:NumPy array initialization (fill with identical values) 【发布时间】:2011-08-18 23:36:39 【问题描述】:我需要创建一个长度为n
的NumPy 数组,其中每个元素都是v
。
还有什么比:
a = empty(n)
for i in range(n):
a[i] = v
我知道zeros
和ones
适用于v = 0, 1。我可以使用v * ones(n)
,但它当v
是None
时它不起作用,并且也 s> 会慢很多。
【问题讨论】:
在我的电脑上,对于 0 的情况,在循环中使用a = np.zeros(n)
比 a.fill(0)
快。这与我的预期相反,因为我认为a=np.zeros(n)
需要分配和初始化新内存。如果有人能解释一下,我将不胜感激。
你不能把 None 放在一个 numpy 数组中,因为单元格是用特定的数据类型创建的,而 None 有它自己的类型,实际上是一个指针。
@Camion 是的,我现在知道了 :) 当然v * ones(n)
仍然很糟糕,因为它使用了昂贵的乘法。不过,将*
替换为+
,而v + zeros(n)
在某些情况下会出奇地好(***.com/questions/5891410/…)。
max,而不是在添加 v 之前创建一个带有零的数组,使用 var = np.empty(n)
创建它为空然后用 'var[:] = v' 填充它会更快。 (顺便说一句,np.full()
和这个一样快)
【参考方案1】:
我相信fill
是最快的方法。
a = np.empty(10)
a.fill(7)
您还应该始终避免像在示例中那样进行迭代。一个简单的 a[:] = v
将使用 numpy broadcasting 完成您的迭代。
【讨论】:
谢谢。在查看fill
时,我发现repeat
更适合我的需求。
您介意更新您的答案,说您对a[:]=v
的推荐实际上比fill
总体上更快吗?
@max 更快吗?广播是一种更通用的填充数组的方法,我猜它会更慢或等于 fill
的非常狭窄的用例。【参考方案2】:
您可以使用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
旨在“平铺”一个数组(而不是本例中的标量),但它可以完成这项工作,创建任何大小和维度的预填充数组。
【讨论】:
【参考方案3】:为 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
【讨论】:
为最近的和直接的np.full()
添加时间会很有用。在我的机器上,使用 NumPy 1.8.1,它比不那么直接的 fill()
版本慢了大约 15%(这是出乎意料的,因为 full()
有可能会稍微快一点)。
@DavidSanders:我不确定我是否在关注你:fill()
是最快的解决方案。乘法解要慢得多。
注意:如果速度真的是一个问题,使用 10000
的大小而不是 1e4
会产生明显的差异,出于某种原因(full()
几乎慢 50%,@987654330 @)。
只需将我的结果与full()
相加,当数据类型不是明确的浮点数时,它的运行速度要慢得多。否则,它与这里的最佳方法相当(但稍慢)。
@user2699 我没有注意到这一点,有 100,000 个元素:full(100000, 5)
、full(100000, 5, dtype=float)
、full(100000, 5, dtype=int)
和 a =np.empty(100000); a.fill(5)
在我的机器上都花费大约相同的时间(没有缓存:@ 987654336@) (NumPy 1.11.2)。【参考方案4】:
显然,不仅绝对速度,而且速度顺序(由 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!)
因此,请尝试找出并使用您平台上最快的东西。
【讨论】:
【参考方案5】: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]])
这可以说是创建一个填充了特定值的数组的方式,因为它明确地描述了正在实现的目标(原则上它可以非常有效,因为它执行一项非常具体的任务)。
【讨论】:
这个 full() 方法对我来说效果很好,但我找不到它的一些文档。谁能指出我正确的地方? 您至少可以在 Python shell 中执行help(numpy.full)
。我也很惊讶它不在网络文档中。
在我的系统(Python 2.7,Numpy 1.8)上,np.full() 实际上比 np.empty() 慢一点,然后是 np.fill()。
对于 10,000 个元素,我观察到相同的情况(除了 np.fill()
不存在,应该是 arr.fill()
),相差约 10%。如果差异更大,我会在 NumPy 错误跟踪器中提出问题。 :) 我更喜欢更明确和更清晰的代码,因为执行时间的差异如此之小,所以我一直使用np.full()
。
在我的机器上 np.full() 与 np.array.fill() 的速度相同【参考方案6】:
我想到了np.array(n * [value])
,但显然这比所有其他足够大的n
建议要慢。在可读性和速度方面最好的是
np.full(n, 3.14)
这是与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
>>>[2]*3
[2, 2, 2]
【讨论】:
建议[v] * n
会更直接地与 OP 问题相关。
This answer 已经提到过这种方法。以上是关于NumPy 数组初始化(填充相同的值)的主要内容,如果未能解决你的问题,请参考以下文章