基于Python Record Linkage库的嵌套列表元素比较问题
问题描述
我正在使用Python的record linkage库识别两个DataFrame(简称dfA和dfB)中的匹配实体。其中用于比较的特征列col_X包含嵌套列表,列表元素e_i为整型标识符。我需要计算每对对比样本中,dfA与dfB的col_X列表的相同元素数量。
我的思路是用集合操作生成统计共同元素数量的Series,代码示例:
(dfA.col_x.apply(set) & dfB.col_x.apply(set)).apply(len)
查阅文档后,我尝试继承BaseCompareFeature自定义类:
class CompareElements(BaseCompareFeature): def __init__(self, left_on, right_on, *args, **kwargs): super(CompareElements, self).__init__(left_on, right_on, *args, **kwargs) def _compute_vectorized(self, s1, s2): sets_s1 = s1.apply(set) sets_s2 = s2.apply(set) sim = (sets_s1 & sets_s2).apply(len) return sim
但该方法无法对Series对象sets_s1和sets_s2使用集合运算符,且不能在函数内迭代(对比需通过compare和compute方法执行)。文档示例未覆盖此场景,因已使用其他对比特征,希望仍基于record linkage库解决问题,求可行方案。
可行方案
方法1:重写_compute_vectorized逐元素计算交集长度
直接在自定义类中对每一对元素计算交集长度,适配record linkage的框架要求:
from recordlinkage.base import BaseCompareFeature import pandas as pd class CompareElements(BaseCompareFeature): def __init__(self, left_on, right_on, *args, **kwargs): super().__init__(left_on, right_on, *args, **kwargs) def _compute_vectorized(self, s1, s2): # 遍历每一对列表,计算交集元素数量 return pd.Series([len(set(a) & set(b)) for a, b in zip(s1, s2)], index=s1.index)
这个方法避开了Series直接使用集合运算符的问题,通过逐元素处理实现需求,完全符合record linkage的执行逻辑。
方法2:向量化优化(适用于大数据量)
如果数据规模较大,逐元素遍历效率不足,可以先将列表转成集合数组,再批量计算交集:
import numpy as np import pandas as pd from recordlinkage.base import BaseCompareFeature class CompareElements(BaseCompareFeature): def __init__(self, left_on, right_on, *args, **kwargs): super().__init__(left_on, right_on, *args, **kwargs) def _compute_vectorized(self, s1, s2): # 将Series中的列表转为集合数组 set_arr1 = np.array(s1.apply(set).tolist()) set_arr2 = np.array(s2.apply(set).tolist()) # 批量计算每对集合的交集长度 return pd.Series([len(a & b) for a, b in zip(set_arr1, set_arr2)], index=s1.index)
这种方式在处理大数据量时,比纯列表推导式的效率更高。
方法3:直接使用Compare对象结合自定义函数
如果不想自定义类,可直接通过Compare的add方法传入自定义对比函数:
import recordlinkage import pandas as pd # 初始化比较器 comp = recordlinkage.Compare() # 添加自定义对比逻辑:计算两个列表的交集元素数量 comp.add( recordlinkage.base.CompareFeature( lambda s1, s2: pd.Series([len(set(a) & set(b)) for a, b in zip(s1, s2)]), left_on='col_X', right_on='col_X' ) ) # 传入配对结果和两个DataFrame,生成对比特征 features = comp.compute(pairs, dfA, dfB)
这种方式无需继承类,直接通过匿名函数实现需求,灵活性更强。
内容的提问来源于stack exchange,提问作者mbgzoo
相关产品推荐
相关产品推荐

