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

如何避免重复词形还原Pandas DataFrame中的重复句子以提升效率

高效处理Pandas中重复句子的词形还原方案

给定条件

如下是一个小型Pandas DataFrame示例:

import numpy as np
import pandas as pd

df = pd.DataFrame(
    {
        "user_ip":       ["u7", "u3", "u1", "u9", "u4","u8", "u1", "u2", "u5"],
        "raw_sentence":  ["First sentence!", np.nan, "I go to school everyday!", "She likes chips!", "I go to school everyday!", "This is 1 sample text!", "She likes chips!", "This is the thrid sentence.", "I go to school everyday!"],
    }
  )

对应的DataFrame展示:

user_ipraw_sentence
u7First sentence!
u3NaN
u1I go to school everyday!
u9She likes chips!
u4I go to school everyday!
u8This is 1 sample text!
u1She likes chips!
u2This is the thrid sentence.
u5I go to school everyday!

目标

针对约10万行的大型Pandas DataFrame,避免对raw_sentence列中的重复句子重复执行词形还原操作,提升处理效率,替代当前使用map的策略。

低效的当前解决方案

目前使用.map()结合lambda遍历每一行,调用get_lm()函数获取词形还原结果,代码如下:

import nltk
nltk.download('all', quiet=True, raise_on_error=True,)
STOPWORDS = nltk.corpus.stopwords.words('english')
wnl = nltk.stem.WordNetLemmatizer()
tokenizer = nltk.tokenize.RegexpTokenizer(r'\w+')

def get_lm(input_sent:str="my text!"):
    tks = [ w for w in tokenizer.tokenize(input_sent.lower()) if not w in STOPWORDS and len(w) > 1 and not w.isnumeric() ]
    lms = [ wnl.lemmatize(w, t[0].lower()) if t[0].lower() in ['a', 's', 'r', 'n', 'v'] else wnl.lemmatize(w) for w, t in nltk.pos_tag(tks)] 
    return lms

df["lemma"] = df["raw_sentence"].map(lambda raw: get_lm(input_sent=raw), na_action='ignore')

处理后的结果:

user_ipraw_sentencelemma说明
u7First sentence![first, sentence]首次出现,执行词形还原
u3NaNNaN通过na_action='ignore'忽略空值
u1I go to school everyday![go, school, everyday]首次出现,执行词形还原
u9She likes chips![like, chip]首次出现,执行词形还原
u4I go to school everyday![go, school, everyday]重复句子,无需再次执行词形还原
u8This is 1 sample text![sample, text]首次出现,执行词形还原
u1She likes chips![like, chip]重复句子,无需再次执行词形还原
u2This is the thrid sentence.[thrid, sentence]首次出现,执行词形还原
u5I go to school everyday![go, school, everyday]重复句子,无需再次执行词形还原

高效优化方案

方案1:字典缓存已处理结果

用字典存储已完成词形还原的句子结果,遍历列时先查缓存,存在则直接取用,不存在再处理并存入缓存,彻底避免重复计算。

# 初始化缓存字典
lemma_cache = {}

def get_lm_cached(input_sent: str):
    if pd.isna(input_sent):
        return np.nan
    if input_sent in lemma_cache:
        return lemma_cache[input_sent]
    # 执行原词形还原逻辑
    tks = [w for w in tokenizer.tokenize(input_sent.lower()) if w not in STOPWORDS and len(w) > 1 and not w.isnumeric()]
    lms = [wnl.lemmatize(w, t[0].lower()) if t[0].lower() in ['a', 's', 'r', 'n', 'v'] else wnl.lemmatize(w) for w, t in nltk.pos_tag(tks)]
    # 存入缓存
    lemma_cache[input_sent] = lms
    return lms

df["lemma"] = df["raw_sentence"].apply(get_lm_cached)

方案2:提取唯一句子处理后映射回原表

先提取raw_sentence中的非空唯一值,仅对这些值执行词形还原,再通过映射关系将结果同步回原DataFrame。

# 提取非空的唯一句子
unique_sents = df["raw_sentence"].dropna().unique()
# 生成唯一句子的词形还原结果
unique_lemmas = pd.Series(unique_sents).apply(get_lm)
# 创建句子与结果的映射字典
lemma_map = dict(zip(unique_sents, unique_lemmas))
# 映射回原DataFrame
df["lemma"] = df["raw_sentence"].map(lemma_map)

方案3:分组广播结果

通过groupby按raw_sentence分组,对每组仅执行一次词形还原,再将结果广播到组内所有行。

df["lemma"] = df.groupby("raw_sentence")["raw_sentence"].transform(
    lambda x: get_lm(x.iloc[0]) if not pd.isna(x.iloc[0]) else np.nan
)

效率说明

三种方案都能大幅减少重复计算:

  • 方案1(字典缓存)在句子重复率较高时效率提升最明显,无需额外分组/合并操作,逻辑直接;
  • 方案2适合重复句子占比极高的场景,仅处理唯一值的开销最小;
  • 方案3代码最简洁,但分组操作在数据量极大时,性能略逊于前两者。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:15:27