如何快速过滤词列表中的非高频词?优化Token处理效率
针对你处理1.3亿Token时遇到的效率瓶颈,咱们可以从数据读取、高频词统计、过滤逻辑三个核心环节逐一优化,以下是具体的改进方案:
一、优化数据读取:用
ast.literal_eval替代字符串替换 你原来用字符串切割解析tokens的方式,不仅容易出错(比如token含特殊字符时),效率也不算高。既然tokens是标准的Python列表格式,直接用ast.literal_eval解析更安全高效:
import ast import pandas as pd # 更可靠的tokens解析方式 tokens_df = pd.read_csv('dataset.csv', converters={'tokens': ast.literal_eval})
二、高频词统计:用
collections.Counter替代Pandas GroupBy 处理超大规模Token时,collections.Counter是基于C实现的哈希表统计,比Pandas的groupby+transform快得多,还能减少内存占用:
from collections import Counter import itertools # 用生成器扁平化所有Token,避免一次性加载全量数据到内存 all_tokens = itertools.chain.from_iterable(tokens_df['tokens']) # 统计词频 token_counts = Counter(all_tokens) # 筛选高频词并转成set(保持O(1)的查询效率) frequent_words = {word for word, cnt in token_counts.items() if cnt >= 5} # 按需排序 frequent_words_sorted = sorted(frequent_words)
三、过滤非高频词:用向量化操作替代逐行Apply
原来的逐行Apply+并行虽然比单线程快,但本质还是Python层面的循环。我们可以用两种更高效的方式:
方式1:explode+分组聚合(推荐)
把Token列表拆成单行过滤,再重新聚合回列表,完全利用Pandas的C层面优化,速度比原方案快数倍:
# 展开Token列表为单行 exploded_df = tokens_df.explode('tokens') # 过滤高频词 filtered_exploded = exploded_df[exploded_df['tokens'].isin(frequent_words)] # 重新聚合回原结构 filtered_df = filtered_exploded.groupby('song')['tokens'].agg(list).reset_index()
方式2:列表推导式+swifter自动并行
如果内存足够,直接用列表推导式处理整个Series,配合swifter可自动选择最优并行策略:
import swifter # 用列表推导式替代自定义函数,减少函数调用开销 tokens_df['tokens'] = tokens_df['tokens'].swifter.apply(lambda x: [t for t in x if t in frequent_words])
四、超大规模数据进阶:用Dask处理(内存不足时)
如果1.3亿Token导致内存溢出,用Dask分块处理可以避免内存压力,同时保持并行效率:
import dask.dataframe as dd from dask.multiprocessing import get # Dask分块读取CSV dask_df = dd.read_csv('dataset.csv', converters={'tokens': ast.literal_eval}) # 分布式统计高频词 def count_tokens(df): return pd.Series(Counter(itertools.chain.from_iterable(df['tokens']))) token_counts = dask_df.map_partitions(count_tokens).compute().sum() frequent_words = {word for word, cnt in token_counts.items() if cnt >=5} # 分布式过滤非高频词 def filter_tokens(x): return [t for t in x if t in frequent_words] dask_df['tokens'] = dask_df['tokens'].apply(filter_tokens, meta=('tokens', 'object')) # 导出结果 filtered_df = dask_df.compute() filtered_df.to_csv('filtered_dataset.csv', index=False)
五、其他优化小技巧
- 避免
global变量:把frequent_words作为参数传递给过滤函数,减少全局变量的开销和潜在问题; - 内存释放:处理过程中及时用
del删除不再需要的变量,配合gc.collect()释放内存; - 保持
frequent_words为set类型:你已经做了这一步,非常棒——set的in操作是O(1),比list的O(n)效率高几个数量级。
内容的提问来源于stack exchange,提问作者scorpion2k40
相关产品推荐
相关产品推荐

