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

如何在Pandas中基于另一列多条件检测词汇并高效处理百万行数据?

问题背景

给定输入DataFrame:

import pandas as pd

df_input = pd.DataFrame({'Keyword': {0: 'apple banana, orange',
  1: 'apple orange ?banana "',
  2: 'potato, piercing pot hole',
  3: 'armor hard known'},
 'Returns': {0: 'Fruit; Banana Vendor',
  1: 'Blendor :Kaka Orange',
  2: 'piercing Fruit Banana takes a lot',
  3: 'bullet jacket gun'}})

需要按以下规则生成三个得分列:

  • Score:若Keyword中的任意词汇出现在Returns列中,得1,否则0
  • Score_before:若Keyword中的任意词汇出现在Returns列词汇的前半部分,得1
  • Score_after:若Keyword中的任意词汇出现在Returns列词汇的后半部分,得1

预期输出:

import pandas as pd

df_output = pd.DataFrame({'Keyword': {0: 'apple banana, orange',
  1: 'apple orange ?banana "',
  2: 'potato, piercing pot hole',
  3: 'armor hard known'},
 'Returns': {0: 'Fruit; Banana Vendor',
  1: 'Blendor :Kaka Orange',
  2: 'piercing Fruit Banana takes a lot',
  3: 'bullet jacket gun'},
 'Score': {0: 1, 1: 1, 2: 1, 3: 0},
 'Score_before': {0: 0, 1: 0, 2: 1, 3: 0},
 'Score_after': {0: 0, 1: 1, 2: 0, 3: 0}})

由于数据量达百万行,咨询以下问题:

  • 如何高效进行词汇分词?
  • 是否应使用字符串操作替代分词工具?
  • 若使用自定义分词函数,如何在整个DataFrame上应用?

自定义分词函数:

import nltk
from nltk.tokenize import word_tokenize
nltk.download('punkt')
import string

def tokenize(s):
  translator = str.maketrans('', '', string.punctuation)
  s = s.translate(translator)
  s = word_tokenize(s)
  return s

tokenize('Finity: Stocks%, Direct$ MF, ETF')

解决方案

一、分词效率与工具选择

百万级数据量下,优先用轻量字符串操作替代NLTK这类重型分词工具,原因如下:

  • NLTK的word_tokenize虽精准,但涉及复杂规则解析,速度远慢于原生字符串处理;
  • 你的场景仅需去除标点后按空格拆分,完全可以用字符串操作实现,无需调用分词库。

替代方案(比自定义函数快数倍):

import string

def fast_tokenize(s):
    # 去除标点+按空格拆分+过滤空字符串+统一转小写(避免大小写匹配问题)
    s = s.translate(str.maketrans('', '', string.punctuation))
    return [word.lower() for word in s.split() if word]

二、自定义分词函数的批量应用

如果坚持使用NLTK分词,要避免逐行循环(效率极低),推荐以下两种批量处理方式:

方法1:直接用pandas.Series.apply

import nltk
from nltk.tokenize import word_tokenize
import string
nltk.download('punkt')

def tokenize(s):
    translator = str.maketrans('', '', string.punctuation)
    s = s.translate(translator)
    return [word.lower() for word in word_tokenize(s)]

# 批量处理两列
df_input['Keyword_tokens'] = df_input['Keyword'].apply(tokenize)
df_input['Returns_tokens'] = df_input['Returns'].apply(tokenize)

方法2:用swifter加速(超大数据量首选)

swifter会自动判断用普通apply还是矢量化操作,大幅提升百万行数据的处理速度:

!pip install swifter
import swifter

df_input['Keyword_tokens'] = df_input['Keyword'].swifter.apply(tokenize)
df_input['Returns_tokens'] = df_input['Returns'].swifter.apply(tokenize)

三、得分列的高效生成

基于分词结果,用矢量化操作生成得分列,避免Python循环:

步骤1:拆分Returns的前后半部分

def split_returns(tokens):
    half = len(tokens) // 2
    return tokens[:half], tokens[half:]

# 拆分后生成两列
df_input[['Returns_before', 'Returns_after']] = df_input['Returns_tokens'].apply(lambda x: pd.Series(split_returns(x)))

步骤2:用集合加速成员判断(核心优化)

列表的in操作是O(n),集合是O(1),先把分词结果转为集合:

df_input['Keyword_set'] = df_input['Keyword_tokens'].apply(set)
df_input['Returns_set'] = df_input['Returns_tokens'].apply(set)
df_input['Returns_before_set'] = df_input['Returns_before'].apply(set)
df_input['Returns_after_set'] = df_input['Returns_after'].apply(set)

步骤3:生成得分列

# Score:判断词汇交集是否为空
df_input['Score'] = df_input.apply(lambda row: 1 if row['Keyword_set'] & row['Returns_set'] else 0, axis=1)
# Score_before:判断与前半部分的交集
df_input['Score_before'] = df_input.apply(lambda row: 1 if row['Keyword_set'] & row['Returns_before_set'] else 0, axis=1)
# Score_after:判断与后半部分的交集
df_input['Score_after'] = df_input.apply(lambda row: 1 if row['Keyword_set'] & row['Returns_after_set'] else 0, axis=1)

# 保留目标列得到最终输出
df_output = df_input[['Keyword', 'Returns', 'Score', 'Score_before', 'Score_after']]

四、总结

  1. 百万行数据优先用原生字符串操作分词,比NLTK快数倍;
  2. 必须用NLTK时,搭配swifter加速apply;
  3. 用集合替代列表做成员判断,大幅提升得分计算效率;
  4. 全程避免Python循环,尽量用Pandas矢量化操作或优化后的apply。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 16:55:45