在 Python 中使用 NLTK 的条件频率分布计算语料库中的单词总数(新手)
Count total number of words in a corpus using NLTK's Conditional Frequency Distribution in Python (newbie)
我需要使用 NLTK 包计算某些语料库中的单词数(单词出现次数)。
这是我的语料库:
corpus = PlaintextCorpusReader('C:\DeCorpus', '.*')
以下是我尝试获取每个文档的总字数的方法:
cfd_appr = nltk.ConditionalFreqDist(
(textname, num_appr)
for textname in corpus.fileids()
for num_appr in [len(w) for w in corpus.raw(fileids=textname).replace("\r", " ").replace("\n", " ").split()])
(我手动将字符串拆分为单词,不知何故它比使用 corpus.words()
效果更好,但问题仍然存在,因此无关紧要)。一般来说,这会做同样的(错误的)工作:
cfd_appr = nltk.ConditionalFreqDist(
(textname, num_appr)
for textname in corpus.fileids()
for num_appr in [len(w) for w in corpus.words(fileids=textname)])
这是我输入 cfd.appr.tabulate()
:
得到的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
2022.12.06_Bild 2.txt 3 36 109 40 47 43 29 29 33 23 24 12 8 6 4 2 2 0 0 0 0
2022.12.06_Bild 3.txt 2 42 129 59 57 46 46 35 22 24 17 21 13 5 6 6 2 2 2 0 0
2022.12.06_Bild 4.txt 3 36 106 48 43 32 38 30 19 39 15 14 16 6 5 8 3 2 3 1 0
2022.12.06_Bild 5.txt 1 55 162 83 68 72 46 24 34 38 27 16 12 8 8 5 9 3 1 5 1
2022.12.06_Bild 6.txt 7 69 216 76 113 83 73 52 49 42 37 20 19 9 7 5 3 6 3 0 1
2022.12.06_Bild 8.txt 0 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
但这些是不同长度的单词数。我需要的就是这个(只有一种类型的项目(文本)应该按字数计算):
2022.12.06_Bild 2.txt 451.0
2022.12.06_Bild 3.txt 538.0
2022.12.06_Bild 4.txt 471.0
2022.12.06_Bild 5.txt 679.0
2022.12.06_Bild 6.txt 890.0
2022.12.06_Bild 8.txt 3.0
dtype: float64
即不同长度的所有单词的总和(或使用 DataFrame(cfd_appr).transpose().sum(axis=1)
组成的列的总和。(顺便说一下,如果有某种方法可以为该列设置名称,这也是一个解决方案,但是 .rename({None: 'W. appear.'}, axis='columns')
不起作用,解决方案通常不够清晰。
那么,我需要的是:
1
2022.12.06_Bild 2.txt 451.0
2022.12.06_Bild 3.txt 538.0
2022.12.06_Bild 4.txt 471.0
2022.12.06_Bild 5.txt 679.0
2022.12.06_Bild 6.txt 890.0
2022.12.06_Bild 8.txt 3.0
不胜感激!
让我们首先尝试用臭名昭著的 BookCorpus 复制您的 table,目录结构:
/books_in_sentences
books_large_p1.txt
books_large_p2.txt
在代码中:
from nltk.corpus import PlaintextCorpusReader
from nltk import ConditionalFreqDist
from nltk import word_tokenize
from collections import Counter
import pandas as pd
corpus = PlaintextCorpusReader('books_in_sentences/', '.*')
cfd_appr = ConditionalFreqDist(
(textname, num_appr)
for textname in corpus.fileids()
for num_appr in [len(w) for w in
word_tokenize(corpus.raw(fileids=textname))])
然后 pandas 修改部分:
# Idiom to convert a FreqDist / ConditionalFreqDist into pd.DataFrame.
df = pd.DataFrame([dict(Counter(freqdist))
for freqdist in cfd_appr.values()],
index=cfd_appr.keys())
# Fill in the not-applicable with zeros.
df = df.fillna(0).astype(int)
# If necessary, sort order of columns and add accordingly.
df = df.sort_values(list(df))
# Sum all columns per row -> pd.Series
counts_per_row = df.sum(axis=1)
最后,访问索引系列,例如:
print('books_large_p1.txt', counts_per_row['books_large_p1.txt'])
或者
我鼓励使用上述解决方案,以便您可以使用 DataFrame 进一步操作数字,但如果您真正需要的只是每行的列数,请尝试以下方法。
如果需要避免 pandas 并直接使用 CFD 中的值,那么您将不得不使用 ConditionalFreqDist.values()
并仔细遍历它。
如果我们这样做:
>>> list(cfd_appr.values())
[FreqDist({3: 6, 6: 5, 1: 5, 9: 4, 4: 4, 2: 3, 8: 2, 10: 2, 7: 1, 14: 1}),
FreqDist({4: 10, 3: 9, 1: 5, 7: 4, 2: 4, 5: 3, 6: 3, 11: 1, 9: 1})]
我们将看到一个 FreqDist 列表,每个都对应于键(在本例中为文件名):
>>> list(cfd_appr.keys())
['books_large_p1.txt', 'books_large_p2.txt']
因为我们知道 ,如果我们对每个 Counter 对象的值求和,我们将得到:
>>> [sum(fd.values()) for fd in cfd_appr.values()]
[33, 40]
输出与上述 df.sum(axis=1)
相同的值。
所以把它放在一起:
>>> dict(zip(cfd_appr.keys(), [sum(fd.values()) for fd in cfd_appr.values()]))
{'books_large_p1.txt': 33, 'books_large_p2.txt': 40}
嗯,这是实际需要的:
首先,获取不同长度的单词个数(和我之前做的一样):
cfd_appr = nltk.ConditionalFreqDist(
(textname, num_appr)
for textname in corpus.fileids()
for num_appr in [len(w) for w in corpus.raw(fileids=textname).replace("\r", " ").replace("\n", " ").split()])
然后添加 import DataFrame
as pd
并将 to_frame(1)
添加到我通过对列求和得到的 dtype: float64
系列:
pd.DataFrame(cfd_appr).transpose().sum(axis=1).to_frame(1)
就是这样。但是,如果有人知道如何在 cfd_appr
的定义中对它们求和,那将是更优雅的解决方案。
我需要使用 NLTK 包计算某些语料库中的单词数(单词出现次数)。
这是我的语料库:
corpus = PlaintextCorpusReader('C:\DeCorpus', '.*')
以下是我尝试获取每个文档的总字数的方法:
cfd_appr = nltk.ConditionalFreqDist(
(textname, num_appr)
for textname in corpus.fileids()
for num_appr in [len(w) for w in corpus.raw(fileids=textname).replace("\r", " ").replace("\n", " ").split()])
(我手动将字符串拆分为单词,不知何故它比使用 corpus.words()
效果更好,但问题仍然存在,因此无关紧要)。一般来说,这会做同样的(错误的)工作:
cfd_appr = nltk.ConditionalFreqDist(
(textname, num_appr)
for textname in corpus.fileids()
for num_appr in [len(w) for w in corpus.words(fileids=textname)])
这是我输入 cfd.appr.tabulate()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
2022.12.06_Bild 2.txt 3 36 109 40 47 43 29 29 33 23 24 12 8 6 4 2 2 0 0 0 0
2022.12.06_Bild 3.txt 2 42 129 59 57 46 46 35 22 24 17 21 13 5 6 6 2 2 2 0 0
2022.12.06_Bild 4.txt 3 36 106 48 43 32 38 30 19 39 15 14 16 6 5 8 3 2 3 1 0
2022.12.06_Bild 5.txt 1 55 162 83 68 72 46 24 34 38 27 16 12 8 8 5 9 3 1 5 1
2022.12.06_Bild 6.txt 7 69 216 76 113 83 73 52 49 42 37 20 19 9 7 5 3 6 3 0 1
2022.12.06_Bild 8.txt 0 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
但这些是不同长度的单词数。我需要的就是这个(只有一种类型的项目(文本)应该按字数计算):
2022.12.06_Bild 2.txt 451.0
2022.12.06_Bild 3.txt 538.0
2022.12.06_Bild 4.txt 471.0
2022.12.06_Bild 5.txt 679.0
2022.12.06_Bild 6.txt 890.0
2022.12.06_Bild 8.txt 3.0
dtype: float64
即不同长度的所有单词的总和(或使用 DataFrame(cfd_appr).transpose().sum(axis=1)
组成的列的总和。(顺便说一下,如果有某种方法可以为该列设置名称,这也是一个解决方案,但是 .rename({None: 'W. appear.'}, axis='columns')
不起作用,解决方案通常不够清晰。
那么,我需要的是:
1
2022.12.06_Bild 2.txt 451.0
2022.12.06_Bild 3.txt 538.0
2022.12.06_Bild 4.txt 471.0
2022.12.06_Bild 5.txt 679.0
2022.12.06_Bild 6.txt 890.0
2022.12.06_Bild 8.txt 3.0
不胜感激!
让我们首先尝试用臭名昭著的 BookCorpus 复制您的 table,目录结构:
/books_in_sentences
books_large_p1.txt
books_large_p2.txt
在代码中:
from nltk.corpus import PlaintextCorpusReader
from nltk import ConditionalFreqDist
from nltk import word_tokenize
from collections import Counter
import pandas as pd
corpus = PlaintextCorpusReader('books_in_sentences/', '.*')
cfd_appr = ConditionalFreqDist(
(textname, num_appr)
for textname in corpus.fileids()
for num_appr in [len(w) for w in
word_tokenize(corpus.raw(fileids=textname))])
然后 pandas 修改部分:
# Idiom to convert a FreqDist / ConditionalFreqDist into pd.DataFrame.
df = pd.DataFrame([dict(Counter(freqdist))
for freqdist in cfd_appr.values()],
index=cfd_appr.keys())
# Fill in the not-applicable with zeros.
df = df.fillna(0).astype(int)
# If necessary, sort order of columns and add accordingly.
df = df.sort_values(list(df))
# Sum all columns per row -> pd.Series
counts_per_row = df.sum(axis=1)
最后,访问索引系列,例如:
print('books_large_p1.txt', counts_per_row['books_large_p1.txt'])
或者
我鼓励使用上述解决方案,以便您可以使用 DataFrame 进一步操作数字,但如果您真正需要的只是每行的列数,请尝试以下方法。
如果需要避免 pandas 并直接使用 CFD 中的值,那么您将不得不使用 ConditionalFreqDist.values()
并仔细遍历它。
如果我们这样做:
>>> list(cfd_appr.values())
[FreqDist({3: 6, 6: 5, 1: 5, 9: 4, 4: 4, 2: 3, 8: 2, 10: 2, 7: 1, 14: 1}),
FreqDist({4: 10, 3: 9, 1: 5, 7: 4, 2: 4, 5: 3, 6: 3, 11: 1, 9: 1})]
我们将看到一个 FreqDist 列表,每个都对应于键(在本例中为文件名):
>>> list(cfd_appr.keys())
['books_large_p1.txt', 'books_large_p2.txt']
因为我们知道
>>> [sum(fd.values()) for fd in cfd_appr.values()]
[33, 40]
输出与上述 df.sum(axis=1)
相同的值。
所以把它放在一起:
>>> dict(zip(cfd_appr.keys(), [sum(fd.values()) for fd in cfd_appr.values()]))
{'books_large_p1.txt': 33, 'books_large_p2.txt': 40}
嗯,这是实际需要的:
首先,获取不同长度的单词个数(和我之前做的一样):
cfd_appr = nltk.ConditionalFreqDist(
(textname, num_appr)
for textname in corpus.fileids()
for num_appr in [len(w) for w in corpus.raw(fileids=textname).replace("\r", " ").replace("\n", " ").split()])
然后添加 import DataFrame
as pd
并将 to_frame(1)
添加到我通过对列求和得到的 dtype: float64
系列:
pd.DataFrame(cfd_appr).transpose().sum(axis=1).to_frame(1)
就是这样。但是,如果有人知道如何在 cfd_appr
的定义中对它们求和,那将是更优雅的解决方案。