Python N元语法频率统计

4

我有一个pandas数据框,我想基于一个文本列进行2-gram频率计算。

text_column
This is a book
This is a book that is read
This is a book but he doesn't think this is a book

最终想要的结果是一个2元组的频率计数,但是这个频率计数是针对每个文档中是否存在2元组进行计算,而不是2元组的数量。

因此部分结果将会是:

2 gram         Count
This is          3
a book           3

“这是”和“一本书”在所有三个文本中都出现了,尽管第三个文本有两个,但我只关心这样的2克拉在多少文档中出现过,计数为3,因此不是4。
您有什么想法吗?
谢谢。

你到目前为止尝试了什么? - johnchase
2个回答

4
Pythonic回答(通用写法,可应用于文件/数据帧/任何内容):
c=collections.Counter()
for i in fh:
  x = i.rstrip().split(" ")
  c.update(set(zip(x[:-1],x[1:])))

现在,c中包含每个2-gram的频率。 说明:
  1. 每行被空格拆分成列表。
  2. 然后使用zip()返回长度为2的元组的迭代器(即2-gram)。
  3. 将迭代器传递到set()中以删除冗余数据。
  4. 然后将集合传递到collections.Counter()对象中,该对象会跟踪每个元组出现的次数。您需要导入collections才能使用它。
  5. 现在很容易列出Counter的内容或将其转换为您喜欢的任何其他格式(例如数据框)。
是的,Python真棒。

1
我非常喜欢你的解决方案,比我的好多了!+1 - Matt Messersmith
感谢您的解决方案!QQ:如何将此转换为三元组? - Anita
1
@Abbey 我认为你只需要将最后一行替换为:c.update(set(zip(x[:-2],x[1:-1],x[2:]))) - Bitwise

0
这很C语言风格,但是可行。思路是跟踪每个文档的“当前”二元组,确保它们只被添加一次(cur_bigrams = set()),并在每个文档之后,如果它在当前文档中,则增加全局频率计数器(bigram_freq)。然后根据bigram_freq中的信息构建一个新的数据框,该数据框跨越文档的全局计数器。
bigram_freq = {}
for doc in df["text_column"]:
    cur_bigrams = set()
    words = doc.split(" ")
    bigrams = zip(words, words[1:])
    for bigram in bigrams:
        if bigram not in cur_bigrams: # Add bigram, but only once/doc
            cur_bigrams.add(bigram)
    for bigram in cur_bigrams:
        if bigram in bigram_freq:
            bigram_freq[bigram] += 1
        else:
            bigram_freq[bigram] = 1

result_df = pd.DataFrame(columns=["2_gram", "count"])
row_list = []
for bigram, freq in bigram_freq.items():
    row_list.append([bigram[0] + " " + bigram[1], freq])
for i in range(len(row_list)):
    result_df.loc[i] = row_list[i]

print(result_df)

输出:

           2_gram count
0          a book     3
1            is a     3
2         This is     3
3         is read     1
4         that is     1
5       book that     1
6      he doesn't     1
7         this is     1
8        book but     1
9          but he     1
10     think this     1
11  doesn't think     1

你可以使用更多的函数式编程或列表推导来大幅简化代码。我将把这留给读者作为练习。


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