在python字典中删除带有nan值的条目

时间:2018-06-26 05:28:30

标签: python dictionary

我有傻瓜。 python中的字典:

OrderedDict([(30, ('A1', 55.0)), (31, ('A2', 125.0)), (32, ('A3', 180.0)), (43, ('A4', nan))])

是否可以删除任何值为NaN的条目?我尝试过:

{k: dict_cg[k] for k in dict_cg.values() if not np.isnan(k)}

如果soln同时适用于python 2和python 3,那就太好了

4 个答案:

答案 0 :(得分:5)

由于您拥有熊猫,因此可以在此处利用熊猫的pd.Series.notnull函数,该函数可用于混合dtypes。

>>> import pandas as pd
>>> {k: v for k, v in dict_cg.items() if pd.Series(v).notna().all()}
{30: ('A1', 55.0), 31: ('A2', 125.0), 32: ('A3', 180.0)}

这不是答案的一部分,但可以帮助您了解我如何得出解决方案。尝试直接使用pd.notnull解决此问题时,我遇到了一些奇怪的行为。

dict_cg[43]

>>> dict_cg[43]
('A4', nan)

pd.notnull不起作用。

>>> pd.notnull(dict_cg[43])
True

它将元组视为单个值(而不是值的可迭代)。此外,将其转换为列表然后进行测试也会给出错误的答案。

>>> pd.notnull(list(dict_cg[43]))
array([ True,  True])

由于第二个值是nan,所以我要查找的结果应该是[True, False]。预转换为系列后,它终于可以工作了:

>>> pd.Series(dict_cg[43]).notnull() 
0     True
1    False
dtype: bool

因此,解决方案是对其进行序列化,然后测试值。

沿着相似的路线,另一种(公认的环形交叉路)解决方案是预先转换为object dtype numpy数组,而pd.notnull将直接起作用:

>>> pd.notnull(np.array(dict_cg[43], dtype=object))
Out[151]: array([True,  False])

我想像pd.notnull直接将dict_cg[43]转换为幕后的字符串数组,将NaN呈现为字符串“ nan”,因此不再是“ null”值。

答案 1 :(得分:4)

这应该有效:

for k,v in dict_cg.items():
    if np.isnan(v[1]):
       dict_cg.pop(k)
print dict_cg

输出:

OrderedDict([(30, ('A1', 55.0)), (31, ('A2', 125.0)), (32, ('A3', 180.0))])

答案 2 :(得分:2)

user308827,

问题中的代码似乎混淆了键和值,而忽略了值是元组这一事实。这是一个使用std libs和dict comprehension在python 2,3中工作的内衬:

from collections import OrderedDict
import math

od = OrderedDict([(30, ('A1', 55.0)), (31, ('A2', 125.0)), (32, ('A3', 180.0)), (43, ('A4', float('Nan')))])

no_nans = OrderedDict({k:v for k, v in od.items() if not math.isnan(v[1])})
# OrderedDict([(30, ('A1', 55.0)), (31, ('A2', 125.0)), (32, ('A3', 180.0))])

答案 3 :(得分:1)

您的原始代码实际上没有pandas,并且仅出于过滤NaN的目的导入它似乎过多。但是,您的代码使用的是numpynp)。

假设您的第一行应显示为:

dict_cg = OrderedDict([(30, ('A1', 55.0)), (31, ('A2', 125.0)), (32, ('A3', 180.0)), (43, ('A4', np.nan))])

尽管需要导入默认库numbers,但此行接近于您所能使用的行:

OrderedDict([(k, vs) for k, vs in d.items() if not any ([isinstance(v, numbers.Number) and np.isnan(v) for v in vs])])

这样,您不需要pandas,结果仍然是OrderedDict(就像以前一样),并且由于{{1 }}从左到右进行评估。