如何加速DataFrame词列表无效词移除并避免数据框意外修改?
问题解决指南
一、为啥clean = df会改原df?怎么解决?
原因
Python里clean = df根本没创建新的DataFrame,只是让clean和df指向内存里同一个数据块——说白了就是俩名字管同一份数据,改一个自然另一个也变。
解决方法
用copy()做个独立副本就行:
- 普通情况(列里都是简单数据,没嵌套列表/字典):
clean = df.copy() - 列里有嵌套结构(比如你的
Text列是列表),得用深拷贝确保完全独立:clean = df.copy(deep=True)
二、快速清理非词典词的优化方案
你的原方法慢主要是两个问题:一是valid_words是列表,in判断要遍历整个列表;二是apply本质是逐行循环,效率低。下面是几个靠谱的优化思路:
第一步必做:把有效词转成集合
列表的in操作是O(n),集合是O(1),先转集合,判断速度直接飙升:
valid_set = set(valid_words)
方案1:纯pandas矢量化操作(推荐,最快)
用explode把列表拆成单行单词,筛选后再聚合回列表,全程无显式循环:
# 把每个列表拆成单独的行 exploded_df = clean.explode('Text') # 只留有效词的行 filtered = exploded_df[exploded_df['Text'].isin(valid_set)] # 按原行号重新聚合成列表 clean['Text'] = filtered.groupby(level=0)['Text'].agg(list) # 处理那些原行里没有效词的情况,填充空列表 clean['Text'] = clean['Text'].apply(lambda x: x if isinstance(x, list) else [])
方案2:优化版遍历(简单高效)
虽然还是遍历,但结合集合的快速判断,比原apply快好几倍:
clean['Text'] = clean['Text'].map(lambda x: [word for word in x if word in valid_set]) # 或者直接用列表推导,速度差不多 clean['Text'] = [[w for w in lst if w in valid_set] for lst in clean['Text']]
方案3:Dask并行处理(超大数据量用)
如果以后数据量再翻倍,单线程扛不住,用Dask拆成多块并行处理:
import dask.dataframe as dd # 把pandas转成Dask DataFrame,分区数按你CPU核心数来 ddf = dd.from_pandas(clean, npartitions=4) # 并行处理每一行 ddf['Text'] = ddf['Text'].map(lambda x: [w for w in x if w in valid_set], meta=('Text', 'object')) # 转回pandas clean = ddf.compute()
为啥njit没用?
Numba的njit对字符串列表这类嵌套结构优化很差,它擅长的是数值数组的向量化计算,所以这种文本列表处理场景,纯pandas方案比Numba靠谱多了。
内容的提问来源于stack exchange,提问作者Max Garza
相关产品推荐
相关产品推荐

