将numpy矩阵初始化为零或一个以外的值

dev*_*ium 167 python numpy

我有以下代码:

r = numpy.zeros(shape = (width, height, 9))
Run Code Online (Sandbox Code Playgroud)

它创建一个用零填充的宽x高x 9矩阵.相反,我想知道是否有一种功能或方法来初始化它们而不是NaN.

有没有?无需诉诸手动循环等?

谢谢

u0b*_*6ae 233

你很少需要在numpy中进行向量操作的循环.您可以创建一个未初始化的数组并立即分配给所有条目:

>>> a = numpy.empty((3,3,))
>>> a[:] = numpy.nan
>>> a
array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])
Run Code Online (Sandbox Code Playgroud)

我在a[:] = numpy.nan这里找到了替代方案,a.fill(numpy.nan)并由Blaenk发布:

$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)"
10000 loops, best of 3: 54.3 usec per loop
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a[:] = np.nan" 
10000 loops, best of 3: 88.8 usec per loop
Run Code Online (Sandbox Code Playgroud)

时间表明偏好ndarray.fill(..)作为更快的选择.OTOH,我喜欢numpy的便利实现,你可以在那里为整个切片分配值,代码的意图非常明确.

  • 我同意您的代码的意图更清晰.但感谢无偏见的时间(或者更确切地说,你仍然发布它们的事实),我很感激:) (2认同)
  • 我喜欢这个:`a = numpy.empty((3,3,))*numpy.nan`.它比`fill`更快但比分配方法慢,但它是一个oneliner !! (2认同)
  • 请看这个答案:http://stackoverflow.com/questions/10871220/making-a-matrix-square-and-padding-it-with-desired-value-in-numpy (2认同)
  • 我更喜欢`.fill()`方法,但随着数组变大,速度的差异几乎没有变化. (2认同)
  • ...因为`np.empty([2,5])`创建一个数组,然后`fill()`就地修改该数组,但不返回副本或引用.如果要通过名称调用`np.empty(2,5)`("赋值给变量"),则必须在对其进行就地操作之前执行此操作.如果你做`[1,2,3].插入(1,4)`,就会发生同样的事情.创建列表并插入4,但是不可能获得对列表的引用(因此可以假设它已被垃圾收集).对于像字符串这样的不可变数据,会返回一个副本,因为您无法就地操作.熊猫可以做到这两点. (2认同)

小智 136

另一种选择是使用numpy.fullNumPy 1.8+中提供的选项

a = np.full([height, width, 9], np.nan)
Run Code Online (Sandbox Code Playgroud)

这非常灵活,您可以使用您想要的任何其他数字填充它.

  • 我认为这是*最正确的答案,因为它完全是'完整'的意思.`np.empy((x,y))*np.nan`是一个很好的亚军(兼容旧版本的numpy). (13认同)
  • 这大致和接受的答案一样快. (2认同)
  • @Farnabaz如果将等效代码放入定时循环中,它们几乎是相同的。两种方法基本相等,第一个方法只是在计时器外部获得了“ np.empty”。`python -mtimeit“将numpy导入为np; a = np.empty((1000,1000)); a.fill(np.nan)” 1000个循环,每循环最好3个:381 usc $ python -mtimeit“导入numpy as np; a = np.full((1000,1000),np.nan);“ 1000次循环,最好是3次:每个循环383微秒 (2认同)

Nic*_*mer 36

我比较了建议的速度替代方案,并发现,对于足够大的矢量/矩阵来填充,所有替代方案除外val * ones并且array(n * [val])同样快.

在此输入图像描述


重现情节的代码:

import numpy
import perfplot

val = 42.0


def fill(n):
    a = numpy.empty(n)
    a.fill(val)
    return a


def colon(n):
    a = numpy.empty(n)
    a[:] = val
    return a


def full(n):
    return numpy.full(n, val)


def ones_times(n):
    return val * numpy.ones(n)


def list(n):
    return numpy.array(n * [val])


perfplot.show(
    setup=lambda n: n,
    kernels=[fill, colon, full, ones_times, list],
    n_range=[2**k for k in range(20)],
    logx=True,
    logy=True,
    xlabel='len(a)'
    )
Run Code Online (Sandbox Code Playgroud)


Jor*_*eña 25

你熟悉numpy.nan吗?

您可以创建自己的方法,例如:

def nans(shape, dtype=float):
    a = numpy.empty(shape, dtype)
    a.fill(numpy.nan)
    return a
Run Code Online (Sandbox Code Playgroud)

然后

nans([3,4])
Run Code Online (Sandbox Code Playgroud)

会输出

array([[ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN]])
Run Code Online (Sandbox Code Playgroud)

我在邮件列表线程中找到了这段代码.

  • @MadPhysicist 这完全取决于你的情况。如果您只需初始化一个 NaN 数组,那么是的,自定义函数可能有点过大了。但是,如果您必须在代码中的数十个位置初始化 NaN 数组,那么使用此函数将变得非常方便。 (3认同)
  • @许卡罗。事实并非如此,因为这样的函数已经存在更灵活和更高效的版本,并且在多个其他答案中都提到了。 (2认同)

hob*_*obs 10

如果您不立即回想起.empty.full方法,您可以随时使用乘法:

>>> np.nan * np.ones(shape=(3,2))
array([[ nan,  nan],
       [ nan,  nan],
       [ nan,  nan]])
Run Code Online (Sandbox Code Playgroud)

当然它也适用于任何其他数值:

>>> 42 * np.ones(shape=(3,2))
array([[ 42,  42],
       [ 42,  42],
       [ 42, 42]])
Run Code Online (Sandbox Code Playgroud)

但是@ u0b34a0f6ae 接受的答案要快3倍(CPU周期,而不是脑循环来记住numpy语法;):

$ python -mtimeit "import numpy as np; X = np.empty((100,100));" "X[:] = np.nan;"
100000 loops, best of 3: 8.9 usec per loop
(predict)laneh@predict:~/src/predict/predict/webapp$ master
$ python -mtimeit "import numpy as np; X = np.ones((100,100));" "X *= np.nan;"
10000 loops, best of 3: 24.9 usec per loop
Run Code Online (Sandbox Code Playgroud)


JHB*_*ius 8

这里尚未提及的另一种可能性是使用 NumPy 瓦片:

a = numpy.tile(numpy.nan, (3, 3))
Run Code Online (Sandbox Code Playgroud)

还给出

array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])
Run Code Online (Sandbox Code Playgroud)

更新:我做了速度比较,它不是很快:/它比ones_times小数点慢。


ntg*_*ntg 5

如前所述, numpy.empty() 是要走的路。但是,对于对象,fill() 可能不会完全按照您的想法执行:

In[36]: a = numpy.empty(5,dtype=object)
In[37]: a.fill([])
In[38]: a
Out[38]: array([[], [], [], [], []], dtype=object)
In[39]: a[0].append(4)
In[40]: a
Out[40]: array([[4], [4], [4], [4], [4]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

一种解决方法可以是例如:

In[41]: a = numpy.empty(5,dtype=object)
In[42]: a[:]= [ [] for x in range(5)]
In[43]: a[0].append(4)
In[44]: a
Out[44]: array([[4], [], [], [], []], dtype=object)
Run Code Online (Sandbox Code Playgroud)


Gia*_*lli 5

另一种选择是numpy.broadcast_to(val,n)无论大小如何都以恒定时间返回并且也是最有效的内存(它返回重复元素的视图)。需要注意的是,返回的值是只读的。

以下是使用与Nico Schlömer 的答案相同的基准提出的所有其他方法的性能比较。

在此处输入图片说明