我有一个熊猫数据框架,我想做基于一个文本列的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
“这是”和“一本书”出现在所有三个文本中,尽管第三个文本中每个文本都有两个,因为我只对这两个克出现了多少个文件感兴趣,所以计数是3,所以不是4。
你知道我该怎么做吗?
谢谢
发布于 2018-08-01 05:05:55
Pythonic式的回答(写成通用的,所以可以应用到文件/dataframe/任何地方):
c=collections.Counter()
for i in fh:
x = i.rstrip().split(" ")
c.update(set(zip(x[:-1],x[1:])))
现在c
保持了每2个字母组的频率。
说明:
zip()
返回长度为2(2克)的元组上的迭代器。set()
>d15split >对象中,该对象跟踪每个元组出现的次数。您需要import collections
才能使用它。import collections
)。是的,Python很棒。
发布于 2018-08-01 04:30:37
这是非常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
您可能可以使用更多的函数式样式和/或列表理解对代码进行适当的裁剪。我将把它作为练习留给读者。
https://stackoverflow.com/questions/51620775
复制相似问题