从字典的 defaultdict(list) 中删除 nan 值
Posted
技术标签:
【中文标题】从字典的 defaultdict(list) 中删除 nan 值【英文标题】:remove nan values from defaultdict(list) of dicts 【发布时间】:2022-01-23 06:43:34 【问题描述】:我通过运行一些分析创建了以下代码,并将结果放入 defaultdict(list) 中。之后,我将结果放入 csv 文件中。首先,我想删除 Check2
中包含“nan”值的项目如何删除字典列表中的值?
from numpy import nan
from collections import defaultdict
d = defaultdict(list,
'Address_1': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1' : 8,
'Check2' : 1,
'Name': 'name',
'Address_match': 'address_match_2',
'ID': 'id',
'Type': 'abc',
'Check1' : 20,
'Check2' : nan,
'Name': 'name',
'Address_match': 'address_match_3',
'ID': 'id',
'Type': 'abc',
'Check1' : 27,
'Check2' : nan],
'Address_2': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1' : 30,
'Check2' : 1,
'Name': 'name',
'Address_match': 'address_match_2',
'ID': 'id',
'Type': 'abc',
'Check1' : 38,
'Check2' : nan,
'Name': 'name',
'Address_match': 'address_match_3',
'ID': 'id',
'Type': 'abc',
'Check1' : 12,
'Check2' : nan])
之后我的结果应该是:
d = defaultdict(list,
'Address_1': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1' : 8,
'Check2' : 1],
'Address_2': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1' : 30,
'Check2' : 1
])
【问题讨论】:
nan
来自哪里?需要导入吗?
nan
是 repl 为 float("nan")
提供的内容,但我不确定这是如何影响的
@ShimonCohen 好点它来自数据集中的结果。我有一个算法可以捕获匹配的地址,然后其他信息也在字典中。有些地址有“Check2”值,有些则没有。
缺少 from numpy import nan
和 from collections import defaultdict
以便重现。
【参考方案1】:
你可以这样做:
import math
def remove_nan_att(d, att):
return key: [o for o in d[key] if not math.isnan(o[att])] for key in d
d = remove_nan_att(d, 'Check2')
检查字典,对于每个键,检查其列表并按所需属性过滤 nan 值。
如果 nan
来自 numpy:
from numpy import nan
def remove_nan_att(d, att):
return key: [o for o in d[key] if not o[att] is nan] for key in d
d = remove_nan_att(d, 'Check2')
如果您不想将其用作函数:
att = 'Check2'
d = key: [o for o in d[key] if not o[att] is nan] for key in d
【讨论】:
谢谢,我和其他人一起去了,因为他们不需要我创建函数。欣赏! 没问题 :) 你也可以用这个衬里代替(在你设置att = 'Check2'
之后):d = key: [o for o in d[key] if not o[att] is nan] for key in d
这个功能是为了方便。【参考方案2】:
试试:
df = pd.DataFrame.from_records(d).unstack()
d = df[df.str['Check2'].notna()].unstack(level=0).to_dict('list')
print(d)
# Output:
'Address_1': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1': 8,
'Check2': 1],
'Address_2': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1': 30,
'Check2': 1]
更新
你可以简单地使用双重理解:
d = [k: [v for v in l if pd.notna(v['Check2'])] for k, l in d.items()]
print(d)
# Output:
['Address_1': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1': 8,
'Check2': 1],
'Address_2': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1': 30,
'Check2': 1]]
为了更容易理解,这里是正常循环的版本:
data = defaultdict(list)
for k, l in d.items(): # for each key in d (Address_1, Address_2, ...)
for v in l: # for each record in key 'Name': ...
if pd.notna(v['Check2']): # check the condition
data[k].append(v) # append to the dict
【讨论】:
啊,我的一些键的值长度似乎不同。我得到这个值错误:“ValueError:数组必须都是相同的长度” 感谢双重理解成功了!你介意解释一下它是如何工作的吗? @aero8991。我更新了我的答案。你能检查一下吗?你现在清楚了吗?【参考方案3】:您可以使用dict理解+过滤器(它是过滤字典,其中Check2
在d
的每个列表中不是np.nan
):
out = k: list(filter(lambda x: ~np.isnan(x['Check2']), lst)) for k, lst in d.items()
您可以使用字典理解 + 列表理解来做同样的事情:
out = k: [dct for dct in lst if not np.isnan(dct['Check2'])] for k, lst in d.items()
输出:
'Address_1': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1': 8,
'Check2': 1],
'Address_2': ['Name': 'name',
'Address_match': 'address_match_1',
'ID': 'id',
'Type': 'abc',
'Check1': 30,
'Check2': 1]
【讨论】:
以上是关于从字典的 defaultdict(list) 中删除 nan 值的主要内容,如果未能解决你的问题,请参考以下文章