Python中如何高效清洗列表和字典数据?
有一个列表字典是这样的
l = [{‘name’: ‘aa’, ‘type’: ‘游戏’}, {‘name’: ‘bb’, ‘type’: ‘游戏’}, {‘name’: ‘cc’, ‘type’: ‘学习’}]
类似上述的列表包括含有类型的键的字典,如何过滤掉和大部分类型不一样的字典
比如列表中一共有 8 个字典,6 个字典中类型是游戏,1 个字典中类型是学习,还有个字典中类型是玩耍,如何过滤后面两个
当然类型是不确定的,数量多的不一定是游戏,还可能是吃饭。。或睡觉
有木有大佬给思路
Python中如何高效清洗列表和字典数据?
统计每个类型出现的百分比,然后根据 Zipf’s Law 选一个阈值删掉百分比小的类型。
def clean_list(data_list, remove_values=[None, '', 0], deduplicate=True):
"""
清洗列表数据
参数:
data_list: 待清洗的列表
remove_values: 需要移除的值列表,默认移除None、空字符串和0
deduplicate: 是否去重,默认为True
返回:
清洗后的列表
"""
# 移除指定值
cleaned = [item for item in data_list if item not in remove_values]
# 去重(保持顺序)
if deduplicate:
seen = set()
cleaned = [item for item in cleaned if not (item in seen or seen.add(item))]
return cleaned
def clean_dict(data_dict, remove_keys=[], remove_values=[None, '', 0], deep_clean=False):
"""
清洗字典数据
参数:
data_dict: 待清洗的字典
remove_keys: 需要移除的键列表
remove_values: 需要移除的值列表
deep_clean: 是否深度清洗嵌套结构
返回:
清洗后的字典
"""
cleaned = {}
for key, value in data_dict.items():
# 跳过需要移除的键
if key in remove_keys:
continue
# 深度清洗嵌套结构
if deep_clean:
if isinstance(value, list):
value = clean_list(value, remove_values)
elif isinstance(value, dict):
value = clean_dict(value, remove_keys, remove_values, deep_clean)
# 跳过需要移除的值
if value not in remove_values:
cleaned[key] = value
return cleaned
# 使用示例
if __name__ == "__main__":
# 测试列表清洗
dirty_list = [1, 2, None, 3, '', 2, 0, 4]
print("原始列表:", dirty_list)
print("清洗后:", clean_list(dirty_list))
# 测试字典清洗
dirty_dict = {
'name': 'Alice',
'age': None,
'scores': [85, None, 90, 0, 85],
'empty': '',
'nested': {'a': 1, 'b': None, 'c': [None, 2]}
}
print("\n原始字典:", dirty_dict)
print("清洗后:", clean_dict(dirty_dict, deep_clean=True))
核心思路就是通过列表推导式和字典推导式进行过滤,配合递归处理嵌套结构。对于列表主要处理空值和去重,字典则处理无效键值对和嵌套数据。
建议:根据实际数据特点调整移除的值列表。
数据少的话:
lst = sorted(l, key=(lambda x : x.get(‘type’)))
ret = [[]]
for prv, nxt in zip(lst[:-1], lst[1:]):
…tmp = ret[-1]
…tmp.append(prv)
…if prv[‘type’]!=nxt[‘type’]:
…ret.append([])
tmp = ret[-1]
tmp.append(t[-1])
然后取 ret 里最多的,或者直接用 groupby
[ list(g) for c, g in groupby(lst, key=(lambda x : x.get(‘type’))) ]
但是都需要排序。
或者用 pandas:
import pandas as pd
l= [{‘name’: ‘aa’, ‘type’: ‘游戏’},
{‘name’: ‘cc’, ‘type’: ‘学习’},
{‘name’: ‘bb’, ‘type’: ‘游戏’}] # 可以不用考虑顺序
list(pd.DataFrame(l).groupby(‘type’)) 可以搞定,输出是 n 个 categories 的 tuple 的 list
[(分组名 1,分组 1 数据的 dataframe),(分组名 2,分组 2 数据的 dataframe)…],数据大小可以用 dataframe 的 shape 来确定。
In [40]: list(pd.DataFrame(l).groupby(‘type’))
Out[40]:
[(‘学习’, name type
1 cc 学习), (‘游戏’, name type
0 aa 游戏
2 bb 游戏)]
In [41]: p=list(pd.DataFrame(l).groupby(‘type’))[1][1]
In [42]: p.shape
Out[42]: (2, 2)
In [43]: p
Out[43]:
name type
0 aa 游戏
2 bb 游戏
对一定量的数据,pandas 就可以有很高的处理效率了,如果数据量再大,考虑上 #1 的方法吧。
从第一步我就没想到好方法来统计每个类型出现的百分比
from itertools import groupby
[ list(g) for c, g in groupby(lst, key=(lambda x : x.get(‘type’))) ]
百分比很好统计:
ret = {}
for i in l:
…if not ret.get(i[‘type’]):
…ret[i[‘type’]] = 0
…ret.get(i[‘type’]) +=1
基本上在不知道 type 有多少的情况下也能轻松统计
Sorry,
ret = {}
for i in l:
…if not ret.get(i[‘type’]):
…ret[i[‘type’]] = 0
…ret[i[‘type’]] +=1
谢谢,这个帮大忙了[ list(g) for c, g in groupby(lst, key=(lambda x : x.get(‘type’))) ]
额。。如果 l 变成[{‘name’: ‘aa’, ‘type’: ‘游戏’}, {‘name’: ‘bb’, ‘type’: ‘游戏’}, {‘name’: ‘cc’, ‘type’: ‘学习’}, {‘name’: ‘dd’, ‘type’: ‘游戏’}]
用这个[list(g) for c,g in groupby(l, key=(lambda x: x.get(‘type’)))]居然会拆开他们
输出[[{‘name’: ‘aa’, ‘type’: ‘游戏’}, {‘name’: ‘bb’, ‘type’: ‘游戏’}], [{‘name’: ‘cc’, ‘type’: ‘学习’}], [{‘name’: ‘dd’, ‘type’: ‘游戏’}]]
这就是我不想要的结果了,我还是看看 pandas 中的 group_by
我在 #2 已经说了,这个需要先排序。pandas 可以无视顺序。所以数据量小考虑直接 python sorted + itertools.groupby,数据量大一些考虑 pandas.DataFrame.groupby,如果超超超大就考虑 #1 的办法。

