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

如何基于一列包含另一列值的条件合并两个Pandas DataFrame

如何基于一列包含另一列值的条件合并两个Pandas DataFrame

问题场景

假设我有两个DataFrame A和B,结构如下:

A:                  |  B:
      Code    Price |                    Name   ID
1  ABC1210   128.14 |  1    TEXTABC1211987654  351    (包含A的第2行Code)
2  ABC1211  3620.10 |  2          SAMPLE12345   20    (不包含A中任何Code)
3  ABC1212    96.44 |  3   ABC1220 SAMPLETEXT  164    (包含A的第4行Code)
4  ABC1220    35.78 |  4  Sample ABC1210 Text  776    (包含A的第1行Code)

我想要把A的Code列和B的Name列关联起来,进而合并两个DataFrame,但问题在于,Code的值是作为子字符串出现在Name里的,不是精确匹配,常规的方法好像都不好用。

我之前查过df.str.contains(value)和df.isin(value)这两个方法,但它们好像每次只能处理单个值——比如我没法直接用A["Code"].isin(B["Name"])来实现批量匹配。

我目前能想到的笨办法是:遍历A中Code列的每一个值,去B的Name列里找有没有包含这个Code的行,然后把找到的行关联到对应的Code上,最后用df.merge()合并。但这种循环的方式不仅写起来麻烦,速度肯定也很慢,完全违背了Pandas矢量化操作的初衷。

有没有用Pandas或者Numpy就能实现的高效方法?是不是我漏了什么更巧妙的实现方式?


解决方案

完全不用循环!这里给你几个符合Pandas矢量化思想的高效实现思路:

方法1:正则提取+合并(最推荐,速度最快)

我们可以把A的所有Code拼接成一个正则备选模式,直接从B的Name列里提取匹配的Code,然后再合并:

import pandas as pd

# 先构造示例DataFrame
data_a = {
    "Code": ["ABC1210", "ABC1211", "ABC1212", "ABC1220"],
    "Price": [128.14, 3620.10, 96.44, 35.78]
}
data_b = {
    "Name": ["TEXTABC1211987654", "SAMPLE12345", "ABC1220 SAMPLETEXT", "Sample ABC1210 Text"],
    "ID": [351, 20, 164, 776]
}
A = pd.DataFrame(data_a, index=[1,2,3,4])
B = pd.DataFrame(data_b, index=[1,2,3,4])

# 把A的Code拼接成正则表达式:匹配任意一个完整的Code子串
code_pattern = '|'.join(A["Code"])
# 从B的Name中提取匹配的Code,无匹配则返回NaN
B["Matched_Code"] = B["Name"].str.extract(f'({code_pattern})', expand=False)

# 现在直接用merge合并即可
merged_df = pd.merge(B, A, left_on="Matched_Code", right_on="Code", how="left")
print(merged_df)

运行后会自动把匹配到的Code对应的Price列合并进来,无匹配的Price会显示NaN,全程都是Pandas矢量化操作,速度比循环快N倍。

方法2:自定义匹配函数(解决Code子串重叠问题)

如果你的Code存在类似ABC12和ABC1210这种包含关系,正则可能会匹配到更短的子串,这时候可以用apply配合自定义函数,确保匹配到完整的目标Code:

# 定义函数:从Name中找出第一个出现在A的Code列表里的子串
def find_matching_code(name, code_list):
    for code in code_list:
        if code in name:
            return code
    return None

# 给B添加匹配的Code列
B["Matched_Code"] = B["Name"].apply(lambda x: find_matching_code(x, A["Code"].tolist()))

# 合并DataFrame
merged_df = pd.merge(B, A, left_on="Matched_Code", right_on="Code", how="left")

这个方法虽然用了apply,但只是在Code列表层面循环,比逐行遍历DataFrame高效得多,还能避免子串重叠的匹配错误。

方法3:Numpy广播匹配(极致性能)

如果数据量不大,也可以用Numpy的广播特性生成匹配矩阵,全程矢量化无Python循环:

import numpy as np

# 生成布尔矩阵:A的每个Code是否在B的每个Name中
match_matrix = np.array([B["Name"].str.contains(code).values for code in A["Code"]])

# 找到每个B行对应的A的Code索引,无匹配则设为-1
match_indices = np.where(match_matrix.any(axis=0), match_matrix.argmax(axis=0), -1)

# 给B添加匹配的Code列
B["Matched_Code"] = np.where(match_indices != -1, A["Code"].iloc[match_indices].values, np.nan)

# 合并
merged_df = pd.merge(B, A, left_on="Matched_Code", right_on="Code", how="left")

这个方法完全依赖Numpy的底层优化,性能拉满,适合对速度要求极高的小数据集场景。


备注:内容来源于stack exchange,提问作者Corsaka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:54:34