在一个 Pandas DataFrame 中使用 NLTK 统计最常见的“两个单词组合”的希伯来语单词数量。

3

我有一个CSV数据文件,其中包含希伯来语中满意度答案的“注释”列。

我想要找出最流行的单词和流行的“2个单词组合”,它们出现的次数,并将它们绘制在条形图上。

目前我的代码:

PYTHONIOENCODING="UTF-8"  
df= pd.read_csv('keep.csv', encoding='utf-8' , usecols=['notes'])
words= df.notes.str.split(expand=True).stack().value_counts()

这将生成一个带有计数器的单词列表,但考虑到希伯来语中的所有停用词,并且不生成“2个单词组合”的频率。我也尝试过这段代码,但它不是我要找的。

 top_N = 30
 txt = df.notes.str.lower().str.replace(r'\|', ' ').str.cat(sep=' ')
 words = nltk.tokenize.word_tokenize(txt)
 word_dist = nltk.FreqDist(words)
 rslt = pd.DataFrame(word_dist.most_common(top_N),
                columns=['Word', 'Frequency'])
 print(rslt)
 print('=' * 60)

我该如何使用nltk完成这个任务?


你如何处理带有希伯来语前缀的单词?הובכמ? - elcuco
2个回答

3
除了jezrael发布的内容,我想介绍另一种实现此目的的方法。由于您正在尝试获取单个词和两个词的频率,因此您还可以利用everygram函数。
给定一个数据框:
import pandas as pd

df = pd.DataFrame()
df['notes'] = ['this is sentence one', 'is sentence two this one', 'sentence one was good']

使用everygrams(word_tokenize(x), 1, 2)获取单词和双词形式,以获取一、二、三个单词组合的组合,您可以将2更改为3等。因此,在您的情况下,应该是:
from nltk import everygrams, word_tokenize

x = df['notes'].apply(lambda x: [' '.join(ng) for ng in everygrams(word_tokenize(x), 1, 2)]).to_frame()

此时,您应该看到:
                                               notes
0  [this, is, sentence, one, this is, is sentence...
1  [is, sentence, two, this, one, is sentence, se...
2  [sentence, one, was, good, sentence one, one w...

现在您可以通过将列表展平并使用value_counts来获取计数:
import numpy as np

flattenList = pd.Series(np.concatenate(x.notes))
freqDf = flattenList.value_counts().sort_index().rename_axis('notes').reset_index(name = 'frequency')

最终输出:
           notes  frequency
0           good          1
1             is          2
2    is sentence          2
3            one          3
4        one was          1
5       sentence          3
6   sentence one          2
7   sentence two          1
8           this          2
9        this is          1
10      this one          1
11           two          1
12      two this          1
13           was          1
14      was good          1

现在绘制图表很容易:
import matplotlib.pyplot as plt 

plt.figure()
flattenList.value_counts().plot(kind = 'bar', title = 'Count of 1-word and 2-word frequencies')
plt.xlabel('Words')
plt.ylabel('Count')
plt.show()

输出:

enter image description here


2

请使用nltk.util.bigrams

计算所有值的bigrams的解决方案:

df = pd.DataFrame({'notes':['aa bb cc','cc cc aa aa']})

top_N = 3
txt = df.notes.str.lower().str.replace(r'\|', ' ').str.cat(sep=' ')
words = nltk.tokenize.word_tokenize(txt)

bigrm = list(nltk.bigrams(words))
print (bigrm)
[('aa', 'bb'), ('bb', 'cc'), ('cc', 'cc'), ('cc', 'cc'), ('cc', 'aa'), ('aa', 'aa')]

word_dist = nltk.FreqDist([' '.join(x) for x in bigrm])
rslt = pd.DataFrame(word_dist.most_common(top_N),
                columns=['Word', 'Frequency'])
print(rslt)
    Word  Frequency
0  cc cc          2
1  aa bb          1
2  bb cc          1

针对每个分裂列的二元组解决方案:

df = pd.DataFrame({'notes':['aa bb cc','cc cc aa aa']})

top_N = 3
f = lambda x: list(nltk.bigrams(nltk.tokenize.word_tokenize(x)))
b = df.notes.str.lower().str.replace(r'\|', ' ').apply(f)
print (b)

word_dist = nltk.FreqDist([' '.join(y) for x in b for y in x])
rslt = pd.DataFrame(word_dist.most_common(top_N),
                    columns=['Word', 'Frequency'])
print(rslt)
    Word  Frequency
0  aa bb          1
1  bb cc          1
2  cc cc          1

如果需要计算由单独的单词组成的二元组:
top_N = 3
f = lambda x: list(nltk.everygrams(nltk.tokenize.word_tokenize(x, 1, 2)))
b = df.notes.str.lower().str.replace(r'\|', ' ').apply(f)
print (b)

word_dist = nltk.FreqDist([' '.join(y) for x in b for y in x])
rslt = pd.DataFrame(word_dist.most_common(top_N),
                    columns=['Word', 'Frequency'])

最后一个图表是由 DataFrame.plot.bar 绘制的:

rslt.plot.bar(x='Word', y='Frequency')

第一个解决方案可行:“计算所有值的双字母组合的解决方案”- 如何将其导出为CSV文件,以便单词不会变成乱码? 第二个和第三个解决方案都没有起作用。我收到了一个错误提示-“期望字符串或类似字节的对象”。 - Lili
@Liron - 你可以将 word_dist = nltk.FreqDist(bigrm) 更改为 word_dist = nltk.FreqDist([' '.join(x) for x in bigrm]) 以适用于字符串,最后对于文件使用 rslt.to_csv('file_out.csv', index=False) - jezrael
另外,我想确保我从第一个解决方案中接收到的所有组合都确实来自同一句话,而不是来自整个列表。 - Lili
rslt.to_csv('file_out.csv', index=False, encoding='utf-8') - 这是我写的代码,但输出的文字仍然是乱码。 - Lili
@Liron - 文件是保密的吗? - jezrael
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接