我试图通过一个数据集中的百万行运行一个函数。
码:
def nlkt(val): val=repr(val) clean_txt = [word for word in val.split() if word.lower() not in stopwords.words('english')] nopunc = [char for char in str(clean_txt) if char not in string.punctuation] nonum = [char for char in nopunc if not char.isdigit()] words_string = ''.join(nonum) return words_string
现在,我使用for循环调用上述函数,以通过百万条记录运行。即使我在具有24核cpu和88 GB Ram的重型服务器上,我仍然看到循环占用了太多时间,并且没有使用那里的计算能力
我正在这样调用上面的函数
data = pd.read_excel(scrPath + "UserData_Full.xlsx", encoding='utf-8') droplist = ['Submitter', 'Environment'] data.drop(droplist,axis=1,inplace=True) #Merging the columns company and detailed description data['Anylize_Text']= data['Company'].astype(str) + ' ' + data['Detailed_Description'].astype(str) finallist =[] for eachlist in data['Anylize_Text']: z = nlkt(eachlist) finallist.append(z)
当我们有几百万条记录时,上面的代码可以正常工作,只是太慢了。它只是excel中的示例记录,但实际数据将存储在DB中,该数据库将运行数亿。有什么办法可以加快操作以更快地通过函数传递数据- 而是使用更多的计算能力?
您的原始图片nlkt()在每行中循环3次。
nlkt()
另外,每次调用时nlkt(),都会一次又一次地重新初始化它们。
stopwords.words('english')
string.punctuation
这些应该是全球性的。
stoplist = stopwords.words('english') + list(string.punctuation)
逐行检查:
val=repr(val)
我不确定为什么需要这样做。但是您可以轻松地将列转换为str类型。这应该在预处理功能之外完成。
str
希望这是不言而喻的:
>>> import pandas as pd >>> df = pd.DataFrame([[0, 1, 2], [2, 'xyz', 4], [5, 'abc', 'def']]) >>> df 0 1 2 0 0 1 2 1 2 xyz 4 2 5 abc def >>> df[1] 0 1 1 xyz 2 abc Name: 1, dtype: object >>> df[1].astype(str) 0 1 1 xyz 2 abc Name: 1, dtype: object >>> list(df[1]) [1, 'xyz', 'abc'] >>> list(df[1].astype(str)) ['1', 'xyz', 'abc']
现在转到下一行:
clean_txt = [word for word in val.split() if word.lower() not in stopwords.words('english')]
使用str.split()很尴尬,应该使用适当的标记器。否则,您的标点符号可能会卡在前面的单词上,例如
str.split()
>>> from nltk.corpus import stopwords >>> from nltk import word_tokenize >>> import string >>> stoplist = stopwords.words('english') + list(string.punctuation) >>> stoplist = set(stoplist) >>> text = 'This is foo, bar and doh.' >>> [word for word in text.split() if word.lower() not in stoplist] ['foo,', 'bar', 'doh.'] >>> [word for word in word_tokenize(text) if word.lower() not in stoplist] ['foo', 'bar', 'doh']
同时检查是否.isdigit()应该一起检查:
.isdigit()
>>> text = 'This is foo, bar, 234, 567 and doh.' >>> [word for word in word_tokenize(text) if word.lower() not in stoplist and not word.isdigit()] ['foo', 'bar', 'doh']
将它们放在一起,您nlkt()应该看起来像这样:
def preprocess(text): return [word for word in word_tokenize(text) if word.lower() not in stoplist and not word.isdigit()]
您可以使用DataFrame.apply:
DataFrame.apply
data['Anylize_Text'].apply(preprocess)