Numpy 确实以不同方式对待 float('nan') 和 float - 转换为 None

lak*_*erz 5 python arrays numpy

我想从普通数组创建一个 Numpy 数组并将nan值转换为None- 但成功取决于天气,第一个值是“普通”浮点数,还是float('nan').

这是我的代码,从初始数组开始:

print(a)
array('d', [3.2345, nan, 2.0, 3.2, 1.0, 3.0])
print(b)
array('d', [nan, nan, 2.0, 3.2, 1.0, 3.0])
Run Code Online (Sandbox Code Playgroud)

现在我想通过向量化函数将所有nan值交换到 Python :None

def convert(x):
    if x != x:
        return None
    else:
        return x

convert_vec = numpy.vectorize(convert)
Run Code Online (Sandbox Code Playgroud)

很简单,但会导致两种不同的结果:

numpy.asarray(convert_vec(a))

array([[ 3.2345,  2.    ,  1.    ], [    nan,  3.2   ,  3.    ]])

numpy.asarray(convert_vec(b))
array([[None, 2.0, 1.0], [None, 3.2, 3.0]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

为什么是这样?是的,我可以看到一个小小的差异 - 第二个有objectas dtype。但使用numpy.asarray(convert_vec(a), dtype=object)固定它 - 两者都有object-dtype但它不会改变结果的差异。

hpa*_*ulj 4

np.nan是浮点值,None不是数字。

In [464]: np.array([1,2,np.nan,3])
Out[464]: array([  1.,   2.,  nan,   3.])

In [465]: np.array([1,2,None,3])
Out[465]: array([1, 2, None, 3], dtype=object)

In [466]: np.array([1,2,None,3],dtype=float)
Out[466]: array([  1.,   2.,  nan,   3.])
Run Code Online (Sandbox Code Playgroud)

如果您尝试创建一个包含 的数组None,则结果将是一个dtype=object数组。如果您坚持使用floatdtype,则将None转换为nan.

在这种vectorize情况下,如果您不指定返回数据类型,它将从第一个元素中推导出来。

你的例子有点令人困惑(你需要编辑它们),但我认为

convert(np.nan) => None
convert(123) => 123
Run Code Online (Sandbox Code Playgroud)

所以

convert_vec([123,nan,...]) => [123, nan, ...],dtype=float
convert_vec([nan,123,...]) => [None, 123,...],dtype=object
Run Code Online (Sandbox Code Playgroud)
  • 尝试转换np.nanNone一个坏主意,除非出于显示目的。

  • vectorize没有明确的结果数据类型规范是一个坏主意

  • 这可能不是一个很好的用途vectorize

这是转换值的另一种方法nan

In [467]: a=np.array([1,2,np.nan,34,np.nan],float)    
In [468]: a
Out[468]: array([  1.,   2.,  nan,  34.,  nan])
In [471]: ind=a!=a   
In [472]: ind
Out[472]: array([False, False,  True, False,  True], dtype=bool)

In [473]: a[ind]=0   # not trying None
In [474]: a
Out[474]: array([  1.,   2.,   0.,  34.,   0.])
Run Code Online (Sandbox Code Playgroud)

或者使用屏蔽数组:

In [477]: am=np.ma.masked_invalid(a)

In [478]: am
Out[478]: 
masked_array(data = [1.0 2.0 -- 34.0 --],
             mask = [False False  True False  True],
       fill_value = 1e+20)

In [479]: am.filled(0)
Out[479]: array([  1.,   2.,   0.,  34.,   0.])
Run Code Online (Sandbox Code Playgroud)