如何基于特征值合并列表中同主体字典?数据清洗技术问询
脏数据合并解决方案思路
原始数据
[{'birthdate': '1966-07-17', 'name': 'WORDS, MARK M'}, {'birthdate': '1966-07-17','name': 'WORDS, MARK MY','placeOfBirth': 'WYOMING','ssn': '999999999'}, {'birthdate': '1966-07-17', 'name': 'WORDS, MARK MY', 'ssn': '999999999'}, {'birthdate': '1970-01-01', 'placeOfBirth': 'MISSOURI', 'ssn': '999999999'}, {'birthdate': '1970-01-01','name': 'BOLLIE PRIDE, CHESTER','placeOfBirth': 'INDIANA','ssn': '999999999'}, {'birthdate': '1966-07-17', 'name': 'WORDS, MARK M', 'ssn': '999999999'}]
核心问题
- 姓名存在中间名缩写与完整形式的差异(如
WORDS, MARK M和WORDS, MARK MY) - 各字典键集合不统一,无固定全局键
- 数据中混有不同主体的条目,需准确区分
解决方案思路
1. 标准化姓名,消除中间名差异
编写姓名标准化函数,忽略中间名的缩写/完整形式差异,提取姓氏和名字作为核心匹配依据:
def standardize_name(name): if not name: return None # 拆分姓氏与名字部分 last_name, first_middle = name.split(', ', 1) first_name, *_ = first_middle.split() # 返回统一格式:姓氏大写, 名字大写 return f"{last_name.upper()}, {first_name.upper()}"
该函数会将WORDS, MARK M和WORDS, MARK MY统一转换为WORDS, MARK,消除中间名带来的匹配障碍。
2. 构建分层优先级的唯一主体标识
根据数据字段的可靠性,按优先级生成唯一匹配键,确保同一主体被准确识别:
- 优先级1:使用
ssn(社会安全号是最可靠的唯一标识,需排除测试用的无效值如999999999) - 优先级2:若无有效
ssn,使用标准化姓名 + birthdate的组合键(本次场景中birthdate在目标主体条目中均存在) - 优先级3:若无姓名,使用birthdate + placeOfBirth + ssn的组合键匹配匿名条目
3. 合并同一主体的字典
用字典作为容器,以唯一标识为键,逐步合并同主体的所有字段:
merged_data = {} raw_data = [ # 原始数据列表 ] for item in raw_data: key_parts = [] # 优先用有效ssn作为标识 if 'ssn' in item and item['ssn'] != '999999999': key_parts.append(item['ssn']) else: # 添加标准化姓名 std_name = standardize_name(item.get('name')) if std_name: key_parts.append(std_name) # 添加birthdate if 'birthdate' in item: key_parts.append(item['birthdate']) # 无姓名时补充出生地 if not std_name and 'placeOfBirth' in item: key_parts.append(item['placeOfBirth']) # 处理无法生成标识的条目 if not key_parts: merged_data.setdefault('unmatched', []).append(item) continue unique_key = '|'.join(key_parts) # 初始化或合并字典 if unique_key not in merged_data: merged_data[unique_key] = {} # 保留非空值,后续非空值覆盖已有空值 for k, v in item.items(): if v and (k not in merged_data[unique_key] or not merged_data[unique_key][k]): merged_data[unique_key][k] = v # 转换为最终列表 final_merged = list(merged_data.values())
4. 后续扩展建议
- 若后续出现新的字段(如
email、phone),可在唯一标识生成逻辑中加入对应字段,提升匹配准确性 - 对于无法自动匹配的
unmatched条目,标记后进行人工核查处理 - 若存在更多姓名格式差异(如姓氏缩写、大小写混乱),可扩展姓名标准化函数的处理逻辑
内容的提问来源于stack exchange,提问作者Joffin21
相关产品推荐
相关产品推荐

