为什么在处理DataFrame时我的NLTK函数变慢?

发布于 2021-01-29 14:10:25

我试图通过一个数据集中的百万行运行一个函数。

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

关注者
0
被浏览
123
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    您的原始图片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)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看