我正在尝试从中等大小(18k 行)的 pandas 数据框中删除非字典单词,但我的方法非常慢。基本上,我尝试过进行列表理解并将其应用于整个数据框。这可行,但速度非常慢,而且我还没有成功矢量化这个过程。我该怎么做?
我的方法似乎还同时影响多个数据帧,这是我不希望发生的。我该如何解决这个问题?
下面的代码代表了我所采取的方法,只是数据少得多:
import pandas as pd
df = pd.DataFrame({'Text': [['this', 'is', 'an', 'apple'],
['this', 'is', 'a', 'carrot'],
['this', 'is', 'a', 'steak']],
'Class': ['fruit', 'vegetable', 'meat']})
valid_words = ['apple', 'carrot', 'steak']
def dictwords(text):
valid_text = [word for word in text if word in valid_words]
return valid_text
clean = df
clean['Text'] = clean['Text'].apply(dictwords)
这可行,但对于我的实际数据来说太慢了。真实的数据集有大约 60k 个独特的单词 - 包括有效的和无效的 - 我试图只保留其中的大约 30k。大约有 18k 行文本。正如人们可能预期的那样,使用 .apply() 来完成此过程需要非常长的时间。
我尝试过 njit/jit 进行并行化,但运气不佳。我可以针对这些数据尝试哪些矢量化/并行化技术,还有比列表理解更好的方法吗?
此外,我发现当我将 dictwords() 应用于干净的数据集时,它似乎也将其应用于 df.我不确定为什么会出现这种情况或如何防止这种情况,因此对此的任何解释也会有所帮助。我测试过的所有 Jupyter Notebook 平台似乎都会发生这种情况。
示例
制作18k样品
import pandas as pd
import numpy as np
# 60k unique word
words = list(map(str, range(0, 60000)))
# target 30k word
valid_words = words[:30000]
# random dataframe 18k rows
np.random.seed(0)
val = np.random.choice(words, (18000, 4)).tolist()
df = pd.DataFrame({'Text': val})
df
Text
0 [2732, 43567, 42613, 52416]
1 [45891, 21243, 30403, 32103]
2 [41993, 57043, 20757, 55026]
... ...
17997 [6688, 22472, 36124, 56143]
17998 [55253, 29436, 4113, 22639]
17999 [1128, 12103, 39056, 28174]
18000 rows × 1 columns
代码
虽然不是完整的向量化操作,但可以将创建 DataFrame 并用 NaN 替换不在
valid_words
中的值的过程向量化。如果您将其聚合回列表,这将比您的任务更快。
out = (pd.DataFrame(df['Text'].tolist())[lambda x: x.isin(valid_words)]
.apply(lambda x: list(x.dropna()),axis=1)
)
出
0 [2732]
1 [21243]
2 [20757]
...
17997 [6688, 22472]
17998 [29436, 4113, 22639]
17999 [1128, 12103, 28174]
Length: 18000, dtype: object
执行时间如下:
970 ms ± 50.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)