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

如何在Pandas中实现列的双向部分字符串匹配

解决双向部分匹配的Pandas筛选问题

首先咱们先优化你原来的代码——用iterrows循环再逐行拼接DataFrame的方式效率很低,Pandas的核心优势就是矢量化操作,咱们可以直接用布尔索引来简化实现。

原需求:筛选email以username开头的行

你原本的需求可以用一行代码搞定,完全不需要循环:

import pandas as pd

d = { 'ID': ['1', '4', '5', '9'], 'username': ['haabi.g', 'pugal.g', 'janani.g', 'hajacob.h'], 'email': ['abi@gmail.com', 'pugal.g@yahoo.in', 'jan232@gmail.com', 'jacob@hoi.com'], }
df1 = pd.DataFrame(d)

# 原条件:email以username开头
mask_startswith = df1['email'].str.startswith(df1['username'])
result_startswith = df1[mask_startswith]
print(result_startswith)

这段代码会输出你原本得到的pugal.g那一行,效率比循环实现高得多。

扩展需求:筛选username与email存在部分匹配的行

现在要实现双向部分匹配——也就是只要两者存在互相包含的部分(比如email包含username的子串,或username包含email的本地前缀子串),就保留该行。咱们可以定义一个更宽泛的布尔掩码来覆盖这些场景:

简洁实现(适合中小数据集)

# 定义双向匹配的复合条件:
# 1. email以username开头(原条件)
# 2. username出现在email的@前缀部分
# 3. email的@前缀部分出现在username中
mask_partial = (
    df1['email'].str.startswith(df1['username'])
    | df1.apply(lambda row: row['username'] in row['email'].split('@')[0], axis=1)
    | df1.apply(lambda row: row['email'].split('@')[0] in row['username'], axis=1)
)

# 应用掩码得到结果
result_partial = df1[mask_partial]
print(result_partial)

运行这段代码后,你会得到所有4行数据,正好符合双向部分匹配的预期:

  • 第一行:abi(email的@前缀)在haabi.g(username)中
  • 第二行:email直接以username开头
  • 第三行:jan(email前缀的一部分)在janani.g(username)中
  • 第四行:jacob(email的@前缀)在hajacob.h(username)中

高效矢量化实现(适合大数据集)

上面的apply虽然能用,但数据量较大时效率会受影响。咱们可以用全矢量化的字符串操作进一步优化:

# 先提取email的@前缀部分
df1['email_local'] = df1['email'].str.split('@').str[0]

# 全矢量化的双向匹配掩码
mask_vectorized = (
    df1['email'].str.startswith(df1['username'])
    | df1['email_local'].str.contains(df1['username'], regex=False)
    | df1['username'].str.contains(df1['email_local'], regex=False)
)

# 筛选后删除临时列
result_vectorized = df1[mask_vectorized].drop('email_local', axis=1)
print(result_vectorized)

这个版本完全依赖Pandas的矢量化API,比apply快数倍,适合处理大规模数据集。

条件逻辑说明

咱们的复合条件覆盖了三种核心匹配场景:

  1. 原需求:email直接以username开头
  2. username是email@前缀的子串(比如username是abc,email是xabc@xxx.com)
  3. email的@前缀是username的子串(比如username是abcde,email是abc@xxx.com)

这样就能确保所有存在部分匹配关系的行都被筛选出来啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:07:38