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

如何高效从Pandas DataFrame文本列中提取匹配的实体名称?

高效提取文本中匹配的实体名称(Pandas大型数据集优化)

问题场景

我有两个Pandas DataFrame:

  • Names:存储大量实体名称,包含ENTITY_NAME列
  • Titles:title列的文本中穿插着Names里的实体名称

现有的提取方法在处理大型数据集时速度极慢,希望得到最快的实体匹配提取方案。

现有实现代码

import pandas as pd
import re

Names = pd.DataFrame({
    'ENTITY_NAME': ['XYZ', 'ABC', 'NGA', 'METRO','DPAC']
})

Titles = pd.DataFrame({
    'title': ['testing some text XYZ testing some text.',
              'XYZ, ABC some random text',
              'some text DPAC random random']
})

# Function to extract ENTITY_NAME if found in title
def extract_entity_name(title, entity_names):
    pattern = '|'.join([r'\b' + re.escape(entity) + r'\b' for entity in entity_names])
    matches = re.findall(pattern, title)
    return ', '.join(matches)

Titles['extracted_entity_name'] = Titles['title'].apply(lambda x: extract_entity_name(x, Names['ENTITY_NAME'].tolist()))

display(Titles.head())

优化方案

1. 预编译正则+矢量化字符串操作(小型实体集首选)

原代码的核心问题是重复构建正则表达式+逐行apply处理,效率极低。优化思路:

  • 仅预编译一次正则表达式
  • 用Pandas原生矢量化字符串方法替代apply(底层C实现,速度提升显著)
  • 按实体长度降序排序,避免短实体截断长实体匹配
import pandas as pd
import re

# 实体按长度降序排序,优先匹配长实体
sorted_entities = sorted(Names['ENTITY_NAME'].tolist(), key=len, reverse=True)
# 预编译正则表达式
pattern = re.compile(r'\b(' + '|'.join(re.escape(e) for e in sorted_entities) + r')\b')

# 矢量化提取并拼接结果
Titles['extracted_entity_name'] = Titles['title'].str.findall(pattern).str.join(', ')

display(Titles.head())

2. Aho-Corasick多模式匹配(超大型实体集首选)

当实体数量达到万级以上时,正则性能会明显下降,此时用pyahocorasick库实现的Aho-Corasick算法,能以接近线性的时间复杂度完成多模式匹配。

实现代码:

import pandas as pd
import ahocorasick

# 构建Aho-Corasick自动机
automaton = ahocorasick.Automaton()
for entity in Names['ENTITY_NAME'].tolist():
    automaton.add_word(entity, entity)
automaton.make_automaton()

# 批量提取函数(加入单词边界校验,避免子串误匹配)
def extract_entities(text):
    matches = set()
    for end_idx, entity in automaton.iter(text):
        start_idx = end_idx - len(entity) + 1
        # 检查前后是否为非字母数字(确保是完整单词)
        left_ok = (start_idx == 0) or (not text[start_idx-1].isalnum())
        right_ok = (end_idx == len(text)-1) or (not text[end_idx+1].isalnum())
        if left_ok and right_ok:
            matches.add(entity)
    return ', '.join(sorted(matches))

Titles['extracted_entity_name'] = Titles['title'].apply(extract_entities)

display(Titles.head())

3. spaCy短语匹配器(复杂规则场景首选)

如果需要结合词性、上下文等NLP规则进行匹配,spaCy的PhraseMatcher是最优选择,性能和灵活性兼顾。

实现代码:

import pandas as pd
import spacy
from spacy.matcher import PhraseMatcher

# 加载轻量spaCy模型
nlp = spacy.load("en_core_web_sm")
matcher = PhraseMatcher(nlp.vocab)
# 添加实体短语模板
patterns = [nlp.make_doc(entity) for entity in Names['ENTITY_NAME'].tolist()]
matcher.add("ENTITY_MATCH", patterns)

def extract_entities(text):
    doc = nlp(text)
    matches = set()
    for _, start, end in matcher(doc):
        matches.add(doc[start:end].text)
    return ', '.join(sorted(matches))

Titles['extracted_entity_name'] = Titles['title'].apply(extract_entities)

display(Titles.head())

性能选型建议

  • 实体数<1000:预编译正则+矢量化操作,代码最简、速度最快
  • 实体数>10000:pyahocorasick的Aho-Corasick算法,性能碾压正则
  • 需要NLP上下文规则:spaCy PhraseMatcher

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:04:53