如何在Python中创建一个指定维度、特定类型且初始化为同一值的数组?

6
我想在Python中创建一些特定尺寸、特定类型的数组,并初始化为相同的值。我可以使用特定大小的NumPy数组,但不确定如何用特定值初始化它们。当然,我不想使用zeros()或ones()。
非常感谢。
4个回答

13

有很多方法可以做到这一点。我想到的第一个单行代码是tile

>>> numpy.tile(2, 25)
array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
       2, 2, 2, 2, 2])

您可以在任何形状中平铺一个值:

>>> numpy.tile(2, (5, 5))
array([[2, 2, 2, 2, 2],
       [2, 2, 2, 2, 2],
       [2, 2, 2, 2, 2],
       [2, 2, 2, 2, 2],
       [2, 2, 2, 2, 2]])

然而,正如下面的一些答案所示,这并不是最快的方法。它适用于任何大小的平铺数组,而不仅仅是单个值,因此如果您只想用单个值填充一个数组,那么最好先分配数组,然后使用切片赋值:

>>> a = numpy.empty((5, 5), dtype=int)
>>> a[:] = 2
>>> a
array([[2, 2, 2, 2, 2],
       [2, 2, 2, 2, 2],
       [2, 2, 2, 2, 2],
       [2, 2, 2, 2, 2],
       [2, 2, 2, 2, 2]])

根据我的几项测试,没有更快的方法。然而,在下面的答案中提到的两种方法同样快速:ndarray.fillnumpy.full

这些测试均在新的Mac电脑上运行OS 10.12.6,使用Python 3.6.1和ipython进行。

def fill_tile(value, shape):
    return numpy.tile(value, shape)

def fill_assign(value, shape, dtype):
    new = numpy.empty(shape, dtype=dtype)
    new[:] = value
    return new

def fill_fill(value, shape, dtype):
    new = numpy.empty(shape, dtype=dtype)
    new.fill(value)
    return new

def fill_full(value, shape, dtype):
    return numpy.full(shape, value, dtype=dtype)

def fill_plus(value, shape, dtype):
    new = numpy.zeros(shape, dtype=dtype)
    new += value
    return new

def fill_plus_oneline(value, shape, dtype):
    return numpy.zeros(shape, dtype=dtype) + value

for f in [fill_assign, fill_fill, fill_full, fill_plus, fill_plus_oneline]:
    assert (fill_tile(2, (500, 500)) == f(2, (500, 500), int)).all()

tile 的确非常慢:

In [3]: %timeit fill_tile(2, (500, 500))
947 µs ± 10.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

切片赋值与ndarray.fillnumpy.full并列第一:

In [4]: %timeit fill_assign(2, (500, 500), int)
102 µs ± 1.37 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [5]: %timeit fill_fill(2, (500, 500), int)
102 µs ± 1.99 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [6]: %timeit fill_full(2, (500, 500), int)
102 µs ± 1.47 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

就地广播加法仅稍慢:

In [7]: %timeit fill_plus(2, (500, 500), int)
179 µs ± 3.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

并且非就地广播加法只比它慢一点:

In [8]: %timeit fill_plus_oneline(2, (500, 500), int)
213 µs ± 4.74 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

谢谢,对于Nd数组它是如何工作的?我想要通用地传递参数,而且不想在之后使用reshape函数。 - Shan
@ Shan,你看了我的第二个例子吗? - senderle
@senderler,是的,我试了一下,可以了,谢谢你的答复。我想采纳这个答案,但还需要等6分钟。 - Shan

6
如何呢:
shape = (100,100)
val = 3.14
dt = np.float
a = np.empty(shape,dtype=dt)
a.fill(val)

通过这种方式,您可以设置和传递参数。此外,在时间方面

In [35]: %timeit a=np.empty(shape,dtype=dt); a.fill(val)
100000 loops, best of 3: 13 us per loop

In [36]: %timeit a=np.tile(val,shape)
10000 loops, best of 3: 102 us per loop

因此,使用fillempty似乎比tile更快。


是的,这也可以工作,但Senderle提出的解决方案更简单且有效...你的解决方案在参数和正确性方面更加优雅。 - Shan
@Shan,没问题(如果你觉得它有用且是更好的解决方案,请点赞并将其标记为正确答案)。 - JoshAdel
@JoshAdel,现在我很困惑该选择哪个答案...我已经接受了一个答案...你的看起来更有效率。 - Shan
@JoshAdel,我不清楚这些在参数方面是否有显著差异——tile只是从参数的类型推断出dtype,你可以通过传递numpy.int64(x)或其他方式来明确它。但速度提升可能是显著的,具体取决于使用情况;在这里,似乎存在可读性和速度之间的小折衷。+1——我很高兴知道这一点。@Shan,你应该接受满足你需求的任何答案。如果你选择接受这个答案,我也不会生气 :) - senderle
@senderle,就传递参数而言,它们本质上是相同的,正如你所说。我只强调将它们设置为函数调用外部,因为OP提到了它。不过,我不知道我的解决方案是否真的比你的更易读。 - JoshAdel

3
从NumPy 1.8开始,您可以使用numpy.full()来实现此功能。
>>> import numpy as np
>>> np.full((3,4), 100, dtype = int)
array([[ 100,  100,  100,  100],
       [ 100,  100,  100,  100],
       [ 100,  100,  100,  100]])

1
似乎比np.zeros((N,M),dtype=int)+100快了2倍。 - hpaulj

-1
你是否在寻找类似这样的东西?
>>> [3 for x in range(10)]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]

您可以将生成的数组传递给 numpy.array

不,列表推导式并不会返回 NumPy 数组。 - user395760

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接