python - 为什么我的 NLTK 函数在处理 DataFrame 时速度很慢?

我正在尝试使用数据集中的百万行来运行一个函数。

  1. 我从数据框中的 CSV 中读取数据
  2. 我使用下拉列表来删除我不需要的数据
  3. 我在 for 循环中通过 NLTK 函数传递它。

代码:

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 中的示例记录,但实际数据将在数据库中运行,数以亿计。有什么方法可以加快操作速度以更快地通过函数传递数据 - 而是使用更多的计算能力?

最佳答案

您原来的 nlkt() 循环遍历每一行 3 次。

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

此外,每次调用 nlkt() 时,您都在一次又一次地重新初始化它们。

  • stopwords.words('english')
  • string.punctuation

这些应该是全局的。

stoplist = stopwords.words('english') + list(string.punctuation)

逐行检查:

val=repr(val)

我不确定您为什么需要这样做。但是您可以轻松地将列转换为 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() 很笨拙,您应该使用合适的分词器。否则,您的标点符号可能会与前面的单词卡在一起,例如

>>> 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() 应该一起检查:

>>> 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 :

data['Anylize_Text'].apply(preprocess)

https://stackoverflow.com/questions/48053823/

相关文章:

android - 我如何从 firebase 实时数据库中获取所有数据

java - 如何修复 Spring Security 中的角色?

python - 从 zip 文件中提取文件并保留修改日期?

python-3.x - 系统退出 : 1 Error on using kivy

shell - zsh 导出路径在直接输入终端时有效,但在输入/.zshrc 时无效

msbuild - msdeploy 错误 ERROR_USER_UNAUTHORIZED : We

angular - Angular 为 4 的 OrderBy 管道

sql-server - 使用 RDS 检索 Agent SQL 作业的当前执行状态

php - 错误 : Apache shutdown unexpectedly error mess

react-native - 如何在 React Native 中制作局部模糊效果