创建用NaN填充的Numpy矩阵


194

我有以下代码:

r = numpy.zeros(shape = (width, height, 9))

它创建一个width x height x 9填充零的矩阵。相反,我想知道是否有一种函数或方法可以将它们初始化为NaNs,而方法很简单。


2
一个警告是NumPy没有整数NA值(与R不同)。请参阅熊猫的陷阱列表。因此np.nan在转换为int时出错。
smci

smci是正确的。对于NumPy,没有这样的NaN值。因此,取决于NaN的类型和NumPy。如果您不知道这一点,将会引起麻烦
MasterControlProgram

Answers:


270

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

>>> a = numpy.empty((3,3,))
>>> a[:] = numpy.nan
>>> a
array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

我已经在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

时序显示优先选择ndarray.fill(..)更快的替代方法。OTOH,我喜欢numpy的便捷实现,在该实现中您可以同时为整个slice分配值,代码的意图非常明确。

请注意,ndarray.fill它是就地执行其操作,因此numpy.empty((3,3,)).fill(numpy.nan)将改为return None


8
我同意您的代码意图更加明确。但是感谢您的时机公正(或者您仍然张贴了这样的事实),我对此表示赞赏:)
Jorge IsraelPeña09年

2
我喜欢这个:a = numpy.empty((3, 3,)) * numpy.nan。它的时间比fill分配方法快但慢,但它是一个单行!
heltonbiker


3
我更喜欢这种.fill()方法,但是随着数组变大,速度的差异几乎没有减少。
naught101 2014年

4
...因为np.empty([2, 5])创建了一个数组,然后fill()就地修改了该数组,但没有返回副本或引用。如果要np.empty(2, 5)使用名称进行调用(“将变量分配给变量”),则必须先进行调用,然后才能对其进行就地操作。如果这样做,也会发生同样的事情[1, 2, 3].insert(1, 4)。创建了列表并插入了4,但是不可能获得对该列表的引用(因此可以假定它已被垃圾回收)。对于诸如字符串之类的不可变数据,将返回一个副本,因为您无法就地操作。熊猫都可以做到。
flutefreak16年

163

另一个选择是使用numpy.full,NumPy 1.8+中可用的一个选项

a = np.full([height, width, 9], np.nan)

这非常灵活,您可以用任何其他所需的数字填充它。


19
我认为这是最正确的答案,因为这实际上是什么full意思。 np.empy((x,y))*np.nan是一个不错的亚军(并且与numpy的旧版本兼容)。
travc 2015年

这要慢一些fill python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)" 100000 loops, best of 3: 13.3 usec per loop python -mtimeit "import numpy as np; a = np.full((100,100), np.nan);" 100000 loops, best of 3: 18.5 usec per loop
Farnabaz

5
@Farnabaz如果将等效代码放入定时循环中,它们几乎是相同的。两种方法基本相同,第一个方法是在计时器外部获得“ np.empty”。python -mtimeit "import numpy as np; a = np.empty((1000,1000)); a.fill(np.nan)" 1000 loops, best of 3: 381 usec per loop $ python -mtimeit "import numpy as np; a = np.full((1000,1000), np.nan);" 1000 loops, best of 3: 383 usec per loop
Scott Staniewicz

47

我比较了建议的速度替代方案,发现对于足够大的向量/矩阵填充,除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)",
)

奇怪的numpy.full(n, val)是,a = numpy.empty(n) .. a.fill(val)它比内部慢,因为它在内部做同样的事情
endolith

26

你熟悉numpy.nan吗?

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

def nans(shape, dtype=float):
    a = numpy.empty(shape, dtype)
    a.fill(numpy.nan)
    return a

然后

nans([3,4])

将输出

array([[ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN]])

我在邮件列表线程中找到了此代码。


1
似乎有点过分了。
疯狂物理学家

@MadPhysicist这完全取决于您的情况。如果您只需要初始化一个NaN数组,那么是的,自定义函数可能会过大。但是,如果您必须在代码中的几十个地方初始化NaN数组,那么拥有此功能将变得非常方便。
Xukrao

1
@徐香郎 考虑到已经存在这种功能的更灵活,更有效的版本,并且在其他多个答案中都提到了,因此并非如此。
疯狂物理学家

10

如果您不立即调用.empty.full方法,则始终可以使用乘法:

>>> np.nan * np.ones(shape=(3,2))
array([[ nan,  nan],
       [ nan,  nan],
       [ nan,  nan]])

当然,它也可以与其他任何数值一起使用:

>>> 42 * np.ones(shape=(3,2))
array([[ 42,  42],
       [ 42,  42],
       [ 42, 42]])

但是@ 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


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)

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

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)

除了与原始问题几乎没有任何关系外,还不错。
疯狂物理学家

1
好吧,这是关于“将numpy矩阵初始化为零或一个以外的其他东西”,如果“其他”是一个对象:)(实际上,谷歌带领我在这里用一个空列表进行初始化)
ntg

3

此处尚未提及的另一种可能性是使用NumPy tile:

a = numpy.tile(numpy.nan, (3, 3))

还给

array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

我不知道速度比较。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.