如何在Pandas中判断含字符串数组的两列是否存在交集?
问题描述
现有一个Pandas DataFrame,A、B两列均存储字符串数组,数据如下:
A B 0 ['1','2','3'] ['1','2','3'] 1 ['1','2','3'] ['1','3','2'] 2 ['1','2'] ['1','3'] 3 ['1','2'] ['1'] 4 ['1','2'] ['3'] 5 ['1'] ['2']
需要新增列C,规则为:当某一行的两个数组存在至少一个共同元素时,C的值为True,否则为False。预期结果如下:
A B C 0 ['1','2','3'] ['1','2','3'] True 1 ['1','2','3'] ['1','3','2'] True 2 ['1','2'] ['1','3'] True 3 ['1','2'] ['1'] True 4 ['1','2'] ['3'] False 5 ['1'] ['2'] False
尝试过以下方法但未成功:
- 直接使用
df['C'] = df['A'] != df['B']:Pandas不支持这种数组直接相等性检查 - 使用
numpy.where()和numpy.array_equal():无法实现自定义的交集判断逻辑,也不能逐行比较二维数组
补充说明:已采纳Series.apply(set)方法,因可读性较好,除非性能出现严重问题。
解决方案
方法一:使用apply结合集合交集(已采纳)
将两列数组转为集合后,判断交集是否非空,可读性强,适合中小规模数据集:
df['C'] = df.apply(lambda row: bool(set(row['A']) & set(row['B'])), axis=1)
若追求更清晰的可读性,可拆分为两步:
# 先将A、B列转成集合 df['A_set'] = df['A'].apply(set) df['B_set'] = df['B'].apply(set) # 判断交集是否存在 df['C'] = df.apply(lambda row: len(row['A_set'] & row['B_set']) > 0, axis=1) # 可选:删除中间辅助列 df = df.drop(['A_set', 'B_set'], axis=1)
方法二:向量化优化(适合大数据集)
如果数据集规模较大,apply的逐行循环性能可能不足,可通过explode结合分组统计实现向量化操作:
# 为每行添加唯一标识 df['idx'] = df.index # 拆分A列数组为多行并标记来源 a_exploded = df[['idx', 'A']].explode('A').rename(columns={'A': 'value'}).assign(source='A') # 拆分B列数组为多行并标记来源 b_exploded = df[['idx', 'B']].explode('B').rename(columns={'B': 'value'}).assign(source='B') # 合并后按行标识和值分组,筛选同时存在A、B来源的行 merged = pd.concat([a_exploded, b_exploded]) common_idx = merged.groupby(['idx', 'value']).filter(lambda x: len(x['source'].unique()) == 2)['idx'].unique() # 生成结果列 df['C'] = df['idx'].isin(common_idx) # 删除临时列 df = df.drop('idx', axis=1)
方法三:列表推导式简洁写法
用列表推导式替代apply,逻辑与方法一一致,写法更简洁:
df['C'] = [bool(set(a) & set(b)) for a, b in zip(df['A'], df['B'])]
内容的提问来源于stack exchange,提问作者jonah0
相关产品推荐
相关产品推荐

