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

我知道zerosones 适用于v = 0, 1。我可以使用v * ones(n),但它vNone 时它不起作用,并且也 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 数组初始化(填充相同的值)的主要内容,如果未能解决你的问题,请参考以下文章

jquery判断数组是不是为空

更新numpy.ndarray中的值

NumPy 填充大型数组的给定边界框坐标内的值

如何用生成器中的值填充 2D Python numpy 数组?

用另一个数组的值初始化一个本地静态常量数组

将C或C99中的结构数组初始化为所有相同的值[重复]