如何使用 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
在写入该行之前的倒数第二行。
我想使用 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
在写入该行之前的倒数第二行。