如何使用 Python 为文本文件以及 class 变量创建 unigram 和 bigram 计数矩阵到 csv 中?

How to create a unigram and bigram count matrix for a text file along with a class variable into csv using Python?

我想使用 Python 为文本文件创建一个单字母组和双字母组计数矩阵以及一个 class 变量到 csv 中 文本文件包含两列,如下所示

Text                                                  Class
I love the movie                                      Pos
I hate the movie                                      Neg

我想要 text 列的 unigram 和 bigram 计数,输出应写入 csv 文件

I     hate      love        movie   the        class
1     0         1           1       1          Pos
1     1         0           1       1          Neg

二元组

I love     love the     the movie     I hate    hate the         class
1            1              1         0          0               Pos
0            0              1         1          1               Neg

谁能帮我把下面的代码改进成上面提到的输出格式?

>>> import nltk
>>> from collections import Counter
>>> fo = open("text.txt")
>>> fo1 = fo.readlines()
>>> for line in fo1:
       bigm = list(nltk.bigrams(line.split()))
       bigmC = Counter(bigm)
       for key, value in bigmC.items():
           print(key, value)

('love', 'the') 1
('the', 'movie') 1
('I', 'love') 1
('I', 'hate') 1
('hate', 'the') 1
('the', 'movie') 1

我已经使您的输入文件更详细一些,这样您就可以相信该解决方案有效:

I love the movie movie
I hate the movie
The movie was rubbish
The movie was fantastic

第一行包含一个单词 twice 否则你无法判断计数器是否正确计数。

解决方法:

import csv
import nltk
from collections import Counter
fo = open("text.txt")
fo1 = fo.readlines()
counter_sum = Counter()
for line in fo1:
       tokens = nltk.word_tokenize(line)
       bigrams = list(nltk.bigrams(line.split()))
       bigramsC = Counter(bigrams)
       tokensC = Counter(tokens)
       both_counters = bigramsC + tokensC
       counter_sum += both_counters
       # This basically collects the whole 'population' of words and bigrams in your document

# now that we have the population can write a csv

with open('unigrams_and_bigrams.csv', 'w', newline='') as csvfile:
    header = sorted(counter_sum, key=lambda x: str(type(x)))
    writer = csv.DictWriter(csvfile, fieldnames=header)
    writer.writeheader()
    for line in fo1:
          tokens = nltk.word_tokenize(line)
          bigrams = list(nltk.bigrams(line.split()))
          bigramsC = Counter(bigrams)
          tokensC = Counter(tokens)
          both_counters = bigramsC + tokensC
          cs = dict(counter_sum)
          bc = dict(both_counters)
          row = {}
          for element in list(cs):
                if element in list(bc):
                  row[element] = bc[element]
                else:
                  row[element] = 0
          writer.writerow(row)

所以,我使用并建立在您最初的方法之上。你没有说你是否想要单独的 csv 中的二元组和一元组,所以假设你想要它们在一起。以其他方式重新编程对您来说并不难。以这种方式积累人口可能最好使用已经内置在 NLP 库中的工具,但有趣的是它可以在更底层完成。顺便说一句,我正在使用 Python 3,如果你需要让它在 Python 2 中工作,你可能需要更改一些东西,例如 list 的使用。

使用的一些有趣的参考资料是 this one on summing counters which was new to me. Also, I had to ask a question 使您的双字母组和单字母组在 CSV 的不同端分组。

我知道代码看起来重复,但您需要先 运行 遍历所有行以获得 csv 的 header,然后才能开始编写它。

这是 libreoffice 中的输出

您的 csv 会变得非常宽,因为它收集了所有的一元字母和双字母字母。如果你真的想在 header 中使用没有括号和逗号的二元组,你可以创建某种函数来实现。最好将它们保留为元组,以防万一您需要在某个时候再次将它们解析为 Python,并且它同样可读..

您没有包含生成 class 列的代码,假设您有它,您可以将字符串 'Class' 附加到 header 之前的 header被写入 csv 以创建该列并填充它,

row['Class'] = sentiment

在写入该行之前的倒数第二行。