You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Key匹配且Value在列表中实现Pandas左连接?

Pandas左连接满足双条件的实现方法

问题描述

现有两个DataFrame:

import pandas as pd

df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'],
                   'value': [1, 2, 3, 4]})

df2 = pd.DataFrame({'key': ['B', 'D', 'D', 'F'],
                   'list_values': [[2, 4, 6], [4, 8], [1, 3, 5], [7, 9]]})

需要实现左连接,同时满足两个条件:

  1. df1['key'] 与 df2['key'] 相等
  2. df1['value'] 存在于 df2['list_values'] 的列表中

期望输出结果:

key  value  list_values
0   A     1       NaN
1   B     2     [2, 4, 6]
2   C     3      NaN
3   D     4     [4, 8]

目前已经通过key完成基础左合并:

merged_df = df1.merge(df2, left_on='key', right_on='key', how='left')

需要补充第二个条件以得到目标结果。

解决方案

有几种实用的方法可以实现这个需求,下面给你详细说明:

方法一:合并后过滤+分组处理

先执行基础左合并,再过滤符合条件的行,最后处理缺失情况:

  1. 执行基础合并:
merged_df = df1.merge(df2, on='key', how='left')
  1. 添加标记列,判断当前value是否在对应的list_values中:
merged_df['is_match'] = merged_df.apply(
    lambda row: row['value'] in row['list_values'] if pd.notna(row['list_values']) else False,
    axis=1
)
  1. 按key和value分组,每组保留匹配成功的行;无匹配则将list_values设为NaN:
result = merged_df.groupby(['key', 'value']).apply(
    lambda group: group[group['is_match']].head(1) if group['is_match'].any() else group.assign(list_values=pd.NA).head(1)
).reset_index(drop=True)
  1. 删除多余的标记列:
result = result.drop('is_match', axis=1)

方法二:先预处理df2再合并(效率更高)

先将df2的列表拆分为单行元素,实现精准匹配后再关联回原列表:

  1. 拆分df2的list_values,同时保留原列表数据:
df2_expanded = df2.explode('list_values').rename(columns={'list_values': 'value'})
df2_expanded['value'] = df2_expanded['value'].astype(int)
  1. 通过key和value合并df1与展开后的df2,再关联回原列表:
temp = df1.merge(df2_expanded, on=['key', 'value'], how='left')
temp = temp.merge(df2, on='key', suffixes=('', '_original'))
  1. 筛选匹配的原列表,其余设为NaN后去重:
temp['list_values'] = temp.apply(
    lambda row: row['list_values_original'] if row['value'] in row['list_values_original'] else pd.NA,
    axis=1
)
result = temp[['key', 'value', 'list_values']].drop_duplicates(subset=['key', 'value'])

方法三:简洁版——过滤+补全缺失行

先完成合并,过滤出符合条件的行,再补全df1中未匹配的行:

merged_df = df1.merge(df2, on='key', how='left')
# 筛选满足条件的行
matched_rows = merged_df[merged_df.apply(lambda x: x['value'] in x['list_values'], axis=1)]
# 补全未匹配的行并设置list_values为NaN
unmatched_rows = df1[~df1.index.isin(matched_rows.index)].assign(list_values=pd.NA)
# 合并并按原顺序排序
result = pd.concat([matched_rows, unmatched_rows]).sort_index().reset_index(drop=True)

内容的提问来源于stack exchange,提问作者Galat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:20:37