如何使用字典将 numpy 中的 NaN 映射到值?
How to map NaN in numpy to values using dictionary?
我有一本将数值映射到标签的字典。我用它为给定的 numpy 数组创建标签。该数组最初包含所有 NaN 值,并且一些元素被填充为非 NaN 值。我想将 NaN 值映射到标签。但是,这失败了:
import numpy as np
# make array with all NaNs
a = np.ones(5) * np.nan
# populate some of it with non-NaN values
a[0] = 1
a[1] = 2
l = {"1": "one", 2: "two", np.nan: "NA"}
for k in l:
if k == np.nan:
print l[k]
# this returns false
print (np.nan in a)
这是因为数组的初始化吗?为什么 np.nan
不等于 a
中的 NaN 值?
我正在尝试获取以下的工作版本:
print l[a[3]] # should print "NA", not raise keyerror
关于 NaN
的一件有趣的事情是 IEEE
指定 NaN
不等于 任何东西(包括它自己)。 Numpy 和 python 通常遵循此规则。
>>> NaN = float('nan')
>>> NaN == NaN
False
>>> import numpy as np
>>> np.nan == np.nan
False
这应该可以解释为什么您的 print l['k']
语句永远不会打印以及为什么 np.nan in a
不会 return True
.
一种解决方法可能是:
numpy.isnan(a).any() # Check if any element in `a` is `nan`.
如果我对您的评论理解正确,则以下代码片段可以更恰当地说明问题:
>>> import numpy as np
>>> d = {np.nan: 'foo'}
>>> d[np.nan]
'foo'
>>> a = np.array([np.nan])
>>> d[a[0]]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: nan
不幸的是,由于 NaN
的疯狂属性,您在这里无能为力。 numpy
数组本质上是 C-Arrays 保存浮点数。当你有一个 free-floating np.nan
时,它有一个永远不会改变的 ID(内存地址),所以 python 可以通过指针比较来锁定它。这就是为什么第一位与上面的字典一起工作的原因。
不幸的是,当您将 NaN
放入数组时,它会用 NaN
填充数组中的值。在这种情况下,该元素的 ID 是相对于数组中第一个元素的位置的 - 因此 python 无法判断此 NaN
是否与您用来构造的相同数组(因为它不是)。由于 NaN
的属性,现在 ID 比较失败并且相等比较失败,你有点倒霉。
至于你的值 -> 标签转换,你可能可以使用 numpy 内置功能:
label_array = np.empty(a.shape, dtype='|S3')
label_array[np.isnan(a)] = 'NA'
label_array[a == 1] = 'one'
label_array[a == 2] = 'two'
对于中等大小的数组,应该足够快...
请注意,只有当您直接将个和两个放入 a
时,这才有效——如果您已经完成了一些浮点数学运算来计算它们,则无效。例如a[n] = 5. / 2.5
因为精度错误可能会使您得到的数字非常接近 2
而并不完全等于 2
...
NaN 未通过 any 比较检查,包括针对自身。即
NaN == NaN
为假。
因此,您的声明
if k == np.nan:
must return False 对于所有 k 值。相反,试试这个:
if not k == k:
print l[k]
这会产生所需的 "NA" 输出。
请注意,您不能用
来欺骗它
if k != k:
因为这也是 returns False.
这对你有用吗?
import numpy as np
# make array with all NaNs
a = np.ones(5) * np.nan
# populate some of it with non-NaN values
a[0] = 1
a[1] = 2
a[3] = 1
l = {1: "one", 2: "two", "NaN": "NA"}
for k in l:
if not k == k:
print l[k]
# this returns false
print (np.nan in a)
a_label = [l[a[n]] if a[n] in l else l["NaN"] for n in range(len(a))]
print a_label
输出:
False
['one', 'two', 'NA', 'one', 'NA']
您可以创建自己的字典来按照您想要的方式处理 NaN:
class MyDict(dict):
def __getitem__(self, key):
try:
if np.isnan(key):
return 'NA'
except TypeError:
pass
return super(MyDict, self).__getitem__(key)
def __contains__(self, key):
try:
self.__getitem__(key)
return True
except KeyError:
return False
测试一下:
>>> l = MyDict({1: "one", 2: "two"})
>>> l[a[3]]
'NA'
>>> l[a[0]]
'one'
>>> np.nan in l
True
我有一本将数值映射到标签的字典。我用它为给定的 numpy 数组创建标签。该数组最初包含所有 NaN 值,并且一些元素被填充为非 NaN 值。我想将 NaN 值映射到标签。但是,这失败了:
import numpy as np
# make array with all NaNs
a = np.ones(5) * np.nan
# populate some of it with non-NaN values
a[0] = 1
a[1] = 2
l = {"1": "one", 2: "two", np.nan: "NA"}
for k in l:
if k == np.nan:
print l[k]
# this returns false
print (np.nan in a)
这是因为数组的初始化吗?为什么 np.nan
不等于 a
中的 NaN 值?
我正在尝试获取以下的工作版本:
print l[a[3]] # should print "NA", not raise keyerror
关于 NaN
的一件有趣的事情是 IEEE
指定 NaN
不等于 任何东西(包括它自己)。 Numpy 和 python 通常遵循此规则。
>>> NaN = float('nan')
>>> NaN == NaN
False
>>> import numpy as np
>>> np.nan == np.nan
False
这应该可以解释为什么您的 print l['k']
语句永远不会打印以及为什么 np.nan in a
不会 return True
.
一种解决方法可能是:
numpy.isnan(a).any() # Check if any element in `a` is `nan`.
如果我对您的评论理解正确,则以下代码片段可以更恰当地说明问题:
>>> import numpy as np
>>> d = {np.nan: 'foo'}
>>> d[np.nan]
'foo'
>>> a = np.array([np.nan])
>>> d[a[0]]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: nan
不幸的是,由于 NaN
的疯狂属性,您在这里无能为力。 numpy
数组本质上是 C-Arrays 保存浮点数。当你有一个 free-floating np.nan
时,它有一个永远不会改变的 ID(内存地址),所以 python 可以通过指针比较来锁定它。这就是为什么第一位与上面的字典一起工作的原因。
不幸的是,当您将 NaN
放入数组时,它会用 NaN
填充数组中的值。在这种情况下,该元素的 ID 是相对于数组中第一个元素的位置的 - 因此 python 无法判断此 NaN
是否与您用来构造的相同数组(因为它不是)。由于 NaN
的属性,现在 ID 比较失败并且相等比较失败,你有点倒霉。
至于你的值 -> 标签转换,你可能可以使用 numpy 内置功能:
label_array = np.empty(a.shape, dtype='|S3')
label_array[np.isnan(a)] = 'NA'
label_array[a == 1] = 'one'
label_array[a == 2] = 'two'
对于中等大小的数组,应该足够快...
请注意,只有当您直接将个和两个放入 a
时,这才有效——如果您已经完成了一些浮点数学运算来计算它们,则无效。例如a[n] = 5. / 2.5
因为精度错误可能会使您得到的数字非常接近 2
而并不完全等于 2
...
NaN 未通过 any 比较检查,包括针对自身。即
NaN == NaN
为假。
因此,您的声明
if k == np.nan:
must return False 对于所有 k 值。相反,试试这个:
if not k == k:
print l[k]
这会产生所需的 "NA" 输出。
请注意,您不能用
来欺骗它if k != k:
因为这也是 returns False.
这对你有用吗?
import numpy as np
# make array with all NaNs
a = np.ones(5) * np.nan
# populate some of it with non-NaN values
a[0] = 1
a[1] = 2
a[3] = 1
l = {1: "one", 2: "two", "NaN": "NA"}
for k in l:
if not k == k:
print l[k]
# this returns false
print (np.nan in a)
a_label = [l[a[n]] if a[n] in l else l["NaN"] for n in range(len(a))]
print a_label
输出:
False
['one', 'two', 'NA', 'one', 'NA']
您可以创建自己的字典来按照您想要的方式处理 NaN:
class MyDict(dict):
def __getitem__(self, key):
try:
if np.isnan(key):
return 'NA'
except TypeError:
pass
return super(MyDict, self).__getitem__(key)
def __contains__(self, key):
try:
self.__getitem__(key)
return True
except KeyError:
return False
测试一下:
>>> l = MyDict({1: "one", 2: "two"})
>>> l[a[3]]
'NA'
>>> l[a[0]]
'one'
>>> np.nan in l
True