【问题标题】:removing words that appear more than x% in a corpus Python删除在语料库 Python 中出现超过 x% 的单词
【发布时间】:2020-09-05 02:56:23
【问题描述】:

我正在处理一个以标记/单词列表形式存在的大型语料库。语料库包含约 1900,000 个单词,我运行了一个代码来获取最常用的单词,现在语料库有 140,000 个单词。

我想删除出现在文档中超过 95% 且不到 5% 的单词

语料库样本

['problems', 'guess', 'sleep', 'holy']

首先我找到了最常用的词

from nltk.probability import FreqDist

corpus_frequency = FreqDist(corpus)

corpus_commom=corpus_frequency.most_common()

然后,我应用这个 for 循环来查找出现率超过 95% 的单词列表

most_frequent=[mytuple for mytuple in corpus_commom if mytuple[1]<len(corpus*95)/100]

但是这段代码运行时间很长,而且没有返回任何输出。

我也尝试遵循我找到的一些答案并应用 CountVectorizer 但我收到一条错误消息

from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer(min_df=0.05, max_df=0.95, lowercase=True) 
X = cv.fit_transform(corpus)

错误信息

ValueError: After pruning, no terms remain. Try a lower min_df or a higher max_df.

更新

如果我这样做,CountVectorizer 就可以工作

cv = CountVectorizer(corpus,max_df=0.95)
count_vector=cv.fit_transform(corpus)

但它返回一个数字列表。我希望输出是我的语料库(单词列表)过滤。

谁能告诉我如何实现这一目标?谢谢

【问题讨论】:

  • 这看起来不对:if mytuple[1]&lt;len(corpus*95)/100。应该是:if mytuple[1]&lt;len(corpus)*0.95
  • 感谢您的来信。它只是将数字更改为最接近的值。
  • 您对 CountVectorizer 的调用看起来不错,因此您的语料库有问题。您可以尝试制作一个包含 10 个文档的小型语料库并确保它有效。另外,为了确认您的语料库看起来没问题,print(corpus[0]) 的输出是什么?
  • @polm23 请找到我添加到主题的更新
  • @leena:你似乎没有明白这一点。您的行len(corpus*95)/100 将您的语料库乘以 95 倍;它实际上有您的语料库的 95 个副本。那是您代码中的错误。将 95 移到 len(corpus) 之外。

标签: python for-loop text-processing


【解决方案1】:

正如错误所暗示的那样,转换后您没有保留任何术语。 也就是说,每个单词出现超过 95% 或低于 5%。例如:

corpus = ['This is a good sentence',
          'This is a good sentence',
          'This is a good sentence',
          'This is a good sentence',
          'This is a good sentence']
cv = CountVectorizer(min_df=0.05, max_df=0.95) 
X = cv.fit_transform(corpus)

会引发同样的错误。但是当您的语料库有 1900,000 个单词时,这没有任何意义。也许您可以检查您的语料库是否是CountVectorizer 的有效参数。在https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html 中查看更多详细信息。

【讨论】:

  • 谢谢杰森。我在发布我的问题之前阅读了该文档,但我仍然无法使我的代码正常工作。
  • 你的语料库是什么?它是一个字符串列表吗?你能展示你的语料库的前几行吗?
  • 我的语料库样本在主题中。这是一个单词列表。
  • 我设法通过执行此编辑使 countVectorizer 工作:#ignore the word that appear more than 95% in the document cv = CountVectorizer(corpus,max_df=0.95) count_vector=cv.fit_transform(corpus) 但它返回数字,我希望我的语料库被过滤。我想要返回的单词列表中没有出现超过 95% 的单词
【解决方案2】:

这是一些计算列表中每个标记的频率分数的代码。您可以使用分数来执行过滤。

import nltk

def get_frac_dist(token_list):
    '''
    Computes frequency count and fraction of individual words in a list.

    Parameters
    ----------
    token_list : list
        List of all (non-unique) tokens from some corpus

    Returns
    -------
    dict
        Dictionary of { token, (count, fraction) } pairs.
    '''

    token_list = nltk.word_tokenize(content)
    total_token_count = len(token_list)

    freq_dict = nltk.FreqDist(token_list)

    frac_dict = {}
    for token, count in freq_dict.items():
        frac_dict[token] = (count, count / total_token_count)

    return frac_dict

你可以这样使用它:

  1. 打开一个文件,用nltk.word_tokenize()对其进行标记,然后将标记列表传递给get_frac_dist()
with open('speech.txt') as f:
    content = f.read()

token_list = nltk.word_tokenize(content)
frac_dist = get_frac_dist(token_list)
  1. get_frac_dist() 返回一个字典。键是令牌,值是包含(频率计数,频率分数)的元组。让我们看一下字典中的前 10 项。
i = 0
for k, v in frac_dist.items():

    i += 1
    if i > 10:
        break

    token = k
    count = v[0]
    frac = v[1]
    print('%-20s: %5d, %0.5f' % (token, count, frac))

打印出来:

President           :     2, 0.00081
Pitzer              :     1, 0.00040
,                   :   162, 0.06535
Mr.                 :     3, 0.00121
Vice                :     1, 0.00040
Governor            :     1, 0.00040
Congressman         :     2, 0.00081
Thomas              :     1, 0.00040
Senator             :     1, 0.00040
Wiley               :     1, 0.00040
  1. 现在,如果您想获取分数大于或小于某个值的单词,请适当地使用&lt;&gt; 运行循环或列表推导。
l = [ (k, v[0], v[1]) for k, v in frac_dist.items() if v[1] > 0.04 ]
print(l)

打印出来:

[(',', 162, 0.0653489310205728), ('and', 104, 0.04195240016135539), ('the', 115, 0.0463896732553449)]

请注意,您希望获得出现次数超过 95% 的单词可能不会返回任何有效答案。你应该画出单词的分布,看看它们的数量是多少。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多