Press "Enter" to skip to content

在Jupyter Notebook中为GooSeeker分词结果计算tf-idf

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

1 介绍

 

我们发布过一篇文档《 GooSeeker分词和情感分析结果excel表怎样计算tf-idf 》,介绍了在excel中用公式计算tf-idf。本Jupyter notebook想达到相同的目的,但是,用python程序实现对tf-idf的计算。

 

在什幺场合下需要计算tf-idf?《 GooSeeker分词和情感分析结果excel表怎样计算tf-idf 》做了详细说明,在这里就不重复说了。在本notebook中重点对比一下计算tf或者tf-idf会对原始数据产生什幺样的影响。

 

GooSeeker分词和情感分析软件 导出的含有词频和文档频率的表有:

词频表:一个数据集的所有词的词频和文档频率
选词结果表:如果手工筛选了被分析词,那幺这些词的词频和文档频率都存在这个表中
选词矩阵表:上面两个表的词频值都是全局的,就是一个词出现在所有文档的次数,而这个表中的词频分别展示了出现在每个文档的次数,显然,可以用这个表做更进一步的统计计算,比如,进行PCA运算用于降维、计算文档相似度、计算词与词的距离、用社交网络图的方法分析主题组成等等

下面就为这几个表计算tf或者tf-idf。

 

2 使用方法

 

本次分析任务的操作顺序是:

 

 

    1. 在GooSeeker分词和文本分析软件上创建文本分析任务并导入包含待分析内容的excel,分析完成后导出词频表、选词结果表和选词矩阵表

 

    1. 将导出的excel表放在本notebook的data/raw文件夹中

 

    1. 从头到尾执行本notebook的单元

 

 

注意:GooSeeker发布的每个notebook项目目录都预先规划好了,具体参看 Jupyter Notebook项目目录规划参考 。如果要新做一个分析项目,把整个模板目录拷贝一份给新项目,然后编写notebook目录下的ipynb文件。

 

3 修改历史

 

2022-08-18:第一版发布

 

4 版权说明

 

本notebook是GooSeeker大数据分析团队开发的,所分析的源数据是GooSeeker分词和文本分析软件生成的,本notebook中的代码可自由共享使用,包括转发、复制、修改、用于其他项目中。

 

5 准备运行环境

 

5.1 引入需要用到的库

 

# -*- coding: utf-8 -*-
​
import os
import math
import numpy as np
import pandas as pd

 

5.2 常量和配置

 

在我们发布的一系列Jupyter Notebook中,凡是处理GooSeeker分词软件导出的结果文件的,都给各种导出文件起了固定的名字。为了方便大家使用,只要把导出文件放在data/raw文件夹,notebook就会找到导出文件,赋值给对应的文件名变量。下面罗列了可能用到的文件名变量:

file_all_word:词频表
file_chosen_word: 选词结果表
file_seg_effect: 分词效果表
file_word_occurrence_matrix: 选词矩阵表(是否出现)
file_word_frequency_matrix: 文档词频对应矩阵
file_word_document_match: 选词匹配表
file_co_word_matrix: 共词矩阵表

pd.set_option('display.width', 1000)  # 设置字符显示宽度
pd.set_option('display.max_rows', None)  # 设置显示最大
# np.set_printoptions(threshold=np.inf) # threshold 指定超过多少使用省略号,np.inf代表无限大
​
# 存原始数据的目录
raw_data_dir = os.path.join(os.getcwd(), '../../data/raw')
# 存处理后的数据的目录
processed_data_dir = os.path.join(os.getcwd(), '../../data/processed')
filename_temp = pd.Series(['词频','分词效果','选词矩阵','选词匹配','选词结果','共词矩阵'])
file_all_word = ''
file_seg_effect = ''
file_word_occurrence_matrix = ''
file_word_document_match = ''
file_chosen_word = ''
file_co_word_matrix = ''

 

5.3 检测data/raw目录下是否有待分析的GooSeeker分词结果表

 

本notebook只使用选词矩阵表和共词矩阵表,下面的代码将检查data/raw中有没有这两个表,如果没有会报错,后面的程序就没法执行了。

 

# 0:'词频', 1:'分词效果', 2:'选词矩阵', 3:'选词匹配', 4:'选词结果', 5:'共词矩阵'
print(raw_data_dir + '\r
')
​
for item_filename in os.listdir(raw_data_dir):
    if filename_temp[0] in item_filename:
        file_all_word = item_filename
        continue
    if filename_temp[1] in item_filename:
        file_seg_effect = item_filename
        continue
    if filename_temp[2] in item_filename:
        file_word_frequency_matrix = item_filename
        continue
    if filename_temp[4] in item_filename:
        file_chosen_word = item_filename
        continue
    if filename_temp[5] in item_filename:
        file_co_word_matrix = item_filename
        continue
        
if file_all_word:
    print("词频表:", "data/raw/", file_all_word)
else:
    print("词频表:不存在")
    
if file_seg_effect:
    print("分词效果表:", "data/raw/", file_seg_effect)
else:
    print("分词效果表:不存在")
    
if file_word_frequency_matrix:
    print("选词矩阵表:", "data/raw/", file_word_frequency_matrix)
else:
    print("选词矩阵表:不存在")
    
if file_chosen_word:
    print("选词结果表:", "data/raw/", file_chosen_word)
else:
    print("选词结果表:不存在")
​
if file_co_word_matrix:
    print("共词矩阵表:", "data/raw/", file_co_word_matrix)
else:
    print("共词矩阵表:不存在")

 

输出结果像这样:

 

/Users/work/workspace/notebook/GooSeeker分词软件导出的选词矩阵和共词矩阵的关系-二舅/notebook/eda/../../data/raw
词频表: data/raw/ 词频表-知乎-二舅.xlsx
分词效果表: data/raw/ 分词效果-知乎-二舅.xlsx
选词矩阵表: data/raw/ 选词矩阵-知乎-二舅.xlsx
选词结果表: data/raw/ 选词结果-知乎-二舅.xlsx
共词矩阵表: data/raw/ 共词矩阵-知乎-二舅.xlsx

 

6 读取数据表并存入矩阵

 

6.1 词频表

 

词频表含有所有自动分词得到的词,但是不含有手工添加的词。

 

6.1.1 读入Pandas DataFrame

 

df_all_word = pd.read_excel(os.path.join(raw_data_dir, file_all_word))
df_all_word.head()

 

6.1.2 统计总词数

 

参考 Get the number of rows in a Pandas DataFrame ,可以用shape[0]或者len()函数得到DataFrame的行数。

 

#num_word = df_all_word.shape[0]
num_word = len(df_all_word)
num_word

 

输出结果:14217

 

6.1.3 统计总文档数

 

在分词效果表中有所有文档,所以,用这个表统计文档数。先用Pandas读入该表,然后统计文档数。

 

df_seg_effect = pd.read_excel(os.path.join(raw_data_dir, file_seg_effect))
df_seg_effect.head(2)

 

num_doc = df_seg_effect.shape[0]
num_doc

 

输出结果:829

 

6.1.4 增加TF列

 

df_all_word['TF'] = df_all_word['词频'] / num_word
df_all_word.head(5)

 

6.1.5 增加IDF_2列和IDF列和IDF_10列

 

分别对应以2为底的对数,e和10为底的对数,以便对比

 

# math库中的log函数没有能力对一列数据逐个求log,要使用numpy库
#df_all_word['IDF_2'] = math.log2(num_doc / (df_all_word['文档频率'] + 1))
df_all_word['IDF_2'] = np.log2(num_doc / (df_all_word['文档频率'] + 1))
df_all_word['IDF'] = np.log(num_doc / (df_all_word['文档频率'] + 1))
df_all_word['IDF_10'] = np.log10(num_doc / (df_all_word['文档频率'] + 1))
df_all_word.head(5)

 

6.1.6 增加TF-IDF_2列和TF-IDF列和TF-IDF_10列

 

tf-idf = tf * idf,计算很简单

 

df_all_word['TF-IDF_2'] = df_all_word['TF'] * df_all_word['IDF_2']
df_all_word['TF-IDF'] = df_all_word['TF'] * df_all_word['IDF']
df_all_word['TF-IDF_10'] = df_all_word['TF'] * df_all_word['IDF_10']
df_all_word.head()

 

6.2 选词结果表

 

6.2.1 读入Pandas DataFrame

 

df_chosen_word = pd.read_excel(os.path.join(raw_data_dir, file_chosen_word))
df_chosen_word.head()

 

6.2.2 统计选词数

 

num_chosen_word = len(df_chosen_word)
num_chosen_word

 

输出结果:133

 

6.2.3 增加TF列

 

df_chosen_word['TF'] = df_chosen_word['词频'] / num_word
df_chosen_word.head(5)

 

6.2.4 增加IDF_2,IDF,IDF_10列

 

df_chosen_word['IDF_2'] = np.log2(num_doc / (df_chosen_word['文档频率'] + 1))
df_chosen_word['IDF'] = np.log(num_doc / (df_chosen_word['文档频率'] + 1))
df_chosen_word['IDF_10'] = np.log10(num_doc / (df_chosen_word['文档频率'] + 1))
df_chosen_word.head(5)

 

6.2.5 增加TF-IDF_2,TF-IDF,TF-IDF_10列

 

df_chosen_word['TF-IDF_2'] = df_chosen_word['TF'] * df_chosen_word['IDF_2']
df_chosen_word['TF-IDF'] = df_chosen_word['TF'] * df_chosen_word['IDF']
df_chosen_word['TF-IDF_10'] = df_chosen_word['TF'] * df_chosen_word['IDF_10']
df_chosen_word.head()

 

6.3 选词矩阵表

 

6.3.1 读入Pandas DataFrame

 

df_word_frequency_matrix = pd.read_excel(os.path.join(raw_data_dir, file_word_frequency_matrix))
df_word_frequency_matrix.head()

 

6.3.2 统计匹配上的文档数

 

num_chosen_doc = df_word_frequency_matrix.shape[0]
num_chosen_doc

 

输出结果:729

 

6.3.3 创建TF-IDF_2矩阵

 

从一个DataFrame拷贝到另一个DataFrame的方法参看: Pandas Create New DataFrame By Selecting Specific Columns 。也可以参看 Pandas官网关于copy的用法

 

df_word_tfidf_2 = df_word_frequency_matrix.copy()
df_word_tfidf_2.head()

 

6.3.4 在Pandas中像Excel一样做统计

 

参看 SUMIF and COUNTIF in pandas ,该文讲解了跟EXCEL对应的统计方法。

 

为了数出来每个词出现在多少个文档中,需要一长串处理,为了搞清楚这一长串处理是什幺意思,我们分解成多个步骤做演练。

 

6.3.4.1 用切片方法把选词矩阵矩阵中的数字切出来

 

下面这行代码其实生成了一个新DataFrame,只是我们没有赋值给一个变量存下来。

 

df_word_frequency_matrix.iloc[:, 2:].head(10)

 

6.3.4.2 找出符合条件的所有行

 

在上一步的基础上,我们再套一层处理,把数量>0的找出来。下面这行代码其实生成了一个新的DataFrame

 

df_word_frequency_matrix[df_word_frequency_matrix.iloc[:, 2:] > 0].head(10)

 

6.3.4.3 针对每一列统计不是NaN的数量

 

统计结果存到一个新的Series中

 

word_doc_count = df_word_frequency_matrix[df_word_frequency_matrix.iloc[:, 2:] > 0].iloc[:, 2:].count()
word_doc_count.head(20)

 

可以试试怎样从Series中取得统计值

 

print(word_doc_count.iloc[0])
print(word_doc_count.iloc[1])
print(word_doc_count.iloc[2])
print('total ', len(word_doc_count), ' words. Same as ', num_chosen_word)

 

输出结果:

 

403

 

293

 

184

 

total 133 words. Same as 133

 

6.3.4.4 计算TD-IDF_2

 

计算方案1 : 使用下面的公式,df_word_frequency_matrix这个二维结构和word_doc_count这个一维结构一起计算,竟然自动匹配地如此准确。为了验证这个结果,接下来还有计算方案2和计算方案3,计算方法越来越初级。可以看到,计算结果一模一样。

 

df_word_tfidf_2.iloc[:, 2:] = (df_word_frequency_matrix.iloc[:, 2:] / num_word) * np.log2(num_doc / (word_doc_count.iloc[:] + 1))
df_word_tfidf_2.head()

 

计算方案2 :手工写一个循环,循环每一个所选词,注意,循环次数是num_chosen_word,不是num_word。

 

for idx in range(num_chosen_word):
    #print('idx: ', idx, '; value: ', df_word_frequency_matrix.iloc[0, idx + 2])
    df_word_tfidf_2.iloc[:, idx + 2] = (df_word_frequency_matrix.iloc[:, idx + 2] / num_word) * np.log2(num_doc / (word_doc_count.iloc[idx] + 1))
df_word_tfidf_2

 

计算方案3 :手工写一个两层循环,分别循环所选词和匹配上的文档。注意,要用num_chosen_doc,不是num_doc,因为很多文档没有匹配上。

 

for i in range(num_chosen_doc):
    for j in range(num_chosen_word):
        df_word_tfidf_2.iloc[i, j + 2] = (df_word_frequency_matrix.iloc[i, j + 2] / num_word) * np.log2(num_doc / (word_doc_count.iloc[j] + 1))
df_word_tfidf_2.head()

 

6.3.5 把TD-IDF_2保存到excel中

 

在后续的notebook中,我们将用这些数据计算词与词之间的相关度,然后做网络分析,利用一些社会网络分析法进行计算和探索,所以,把计算好的td-idf选词矩阵存入excel中,放在data/processed文件夹中。

 

file_word_tdidf2_matrix = os.path.join(processed_data_dir, 'word_tdidf2_matrix.xlsx')
with pd.ExcelWriter(file_word_tdidf2_matrix, engine='xlsxwriter') as writer:
    df_word_tfidf_2.to_excel(writer, sheet_name='Sheet1')
    workbook  = writer.book
    worksheet = writer.sheets['Sheet1']
    cell_format = workbook.add_format({'text_wrap': True})
    worksheet.set_column('A:Z', cell_format=cell_format)

 

6.3.6 计算其他对数底数的TD-IDF

 

6.3.6.1 计算TD-IDF

 

df_word_tfidf_e = df_word_frequency_matrix.copy()
df_word_tfidf_e.iloc[:, 2:] = (df_word_frequency_matrix.iloc[:, 2:] / num_word) * np.log(num_doc / (word_doc_count.iloc[:] + 1))
df_word_tfidf_e.head()

 

6.3.6.2 把TD-IDF保存到excel中

 

file_word_tdidf_matrix = os.path.join(processed_data_dir, 'word_tdidf_matrix.xlsx')
with pd.ExcelWriter(file_word_tdidf_matrix, engine='xlsxwriter') as writer:
    df_word_tfidf_e.to_excel(writer, sheet_name='Sheet1')
    workbook  = writer.book
    worksheet = writer.sheets['Sheet1']
    cell_format = workbook.add_format({'text_wrap': True})
    worksheet.set_column('A:Z', cell_format=cell_format)

 

6.3.6.3 计算TD-IDF_10

 

df_word_tfidf_10 = df_word_frequency_matrix.copy()
df_word_tfidf_10.iloc[:, 2:] = (df_word_frequency_matrix.iloc[:, 2:] / num_word) * np.log10(num_doc / (word_doc_count.iloc[:] + 1))
df_word_tfidf_10.head()

 

6.3.6.4 把TD-IDF_10保存到excel中

 

file_word_tdidf10_matrix = os.path.join(processed_data_dir, 'word_tdidf10_matrix.xlsx')
with pd.ExcelWriter(file_word_tdidf10_matrix, engine='xlsxwriter') as writer:
    df_word_tfidf_10.to_excel(writer, sheet_name='Sheet1')
    workbook  = writer.book
    worksheet = writer.sheets['Sheet1']
    cell_format = workbook.add_format({'text_wrap': True})
    worksheet.set_column('A:Z', cell_format=cell_format)

 

7 总结

 

上面已经为词频表、选词结果表、选词矩阵计算了TD-IDF,期望压制一下高频词的打分,其实效果很有限:

TF-IDF会微调词频类似的高频词之间的排序
可以很明显调整文档频率极低的词的排序。

后面将利用选词矩阵进行社会网络分析,观察不同对数底数是否会有明显影响,以及对比与原始词频和经过协方差计算后再进行网络分析的不同。

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。