Pandas如何逐行根据cte列集合移除parents列重叠元素
Pandas逐行移除两列集合重叠元素问题解决
问题场景
持有包含parents和cte两列的DataFrame,两列元素均为集合类型,总计6000+行数据,部分行的cte列取值为空集合。
需求为逐行独立计算:用当前行cte列的集合,移除同一行parents列集合中存在的重叠元素,无跨行计算逻辑。此前尝试调用.discard(cte)方法未得到预期结果。
注:所有行独立计算,单行处理结果不参与其他行运算。
复现样例
样例数据构造代码:
import pandas as pd data = {'parents': [{'loan_agreement', 'select', 'opportunity', 'sales.dim_date', 'sales.flat_opportunity_detail', 'dets', 'dets2', 'channel_partner'}, {'seed', 'dw_salesforce.sf_dw_partner_application'}], 'cte': [{'dets', 'dets2'}, {'seed'}]} df = pd.DataFrame(data) df
预期输出效果:对应行cte集合包含的dets、dets2、seed元素从对应行的parents集合中移除,构造预期结果的代码如下:
data = {'parents': [{'loan_agreement', 'select', 'opportunity', 'sales.dim_date', 'sales.flat_opportunity_detail', 'channel_partner'}, {'dw_salesforce.sf_dw_partner_application'}], 'cte': [{'dets', 'dets2'}, {'seed'}]} df_expected = pd.DataFrame(data) df_expected
错误原因
之前调用.discard()方法失效的核心原因:
- 集合的
discard()方法仅支持接收单个可哈希元素作为入参,传入整个cte集合时,方法会把整个集合对象当成单个待删除元素,无法匹配到集合内的单个成员,自然不会删除任何内容 discard()是原地修改方法,返回值为None,如果直接在apply中调用会把parents列的值覆盖为None
解决方案
高性能写法(推荐)
直接利用Pandas Series的逐行集合运算,无需显式循环,6000行数据可瞬间完成计算,且天然兼容cte为空集合的场景(集合减空集返回原集合):
# 逐行计算parents与对应cte的差集,覆盖原parents列 df['parents'] = df['parents'] - df['cte']
该写法等价于调用集合的difference()方法,会返回parents集合中所有不存在于对应行cte集合中的元素,完全匹配需求,且返回新集合不会触发Pandas链式赋值警告。
灵活扩展写法
如果后续需要在逐行处理中增加额外判断逻辑,可以使用apply逐行处理,性能略低于上面的列运算写法,但足够应对6000行的数据规模:
df['parents'] = df.apply(lambda row: row['parents'] - row['cte'], axis=1)
执行上述任意一段代码后,输出的df结果和预期完全一致。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

