机械学习--TF-IDF实战--红楼梦数据处理
目录
一、数据分析
1. 导入模块和初始设置
2. 空白行处理标记
3. 主循环:逐行处理文本
4. 清理工作:关闭文件
代码的整体流程总结:
代码的特点和作用:
二、关键词提取
1. 导入必要的库
2. 遍历文件夹收集文件路径和内容
3. 构建 DataFrame 存储数据
4. 加载自定义资源
5. 分词处理与停用词过滤
代码整体流程总结:
代码的关键作用:
三、TF-IDF模拟
1. 导入必要的库
2. 读取分词后的文本数据
3. 计算 TF-IDF 矩阵
4. 构建 TF-IDF 数据框
5. 定义提取 Top N 关键词的函数
6. 应用函数提取所有文档的关键词
7. 打印结果
代码整体流程总结:
关键概念解释:
四、泛用性
一、代码核心逻辑与可修改点
二、简单修改后的可能作用
三、典型应用场景
1. 文学 / 历史文本分析
2. 学术论文 / 报告整理
3. 企业文档 / 客服记录分析
4. 社交媒体 / 舆情分析
四、总结
现在有一篇红楼梦的文档需要对数据处理一下
数据已经上传,可以自行下载
一、数据分析
这段代码的主要功能是将《红楼梦》的文本文件按照 "卷 第 X" 的标记进行分卷处理,生成多个分卷文件,并过滤掉包含特定广告内容的行。下面我将逐行详细解释这段代码的功能和作用:
1. 导入模块和初始设置
import os # 导入os模块,用于处理文件路径等操作系统相关功能
file = open('红楼梦.txt', encoding='utf-8') # 打开源文件,使用utf-8编码
flag = 0 # 标记是否已经创建过分卷文件,0表示未创建,1表示已创建
juan_file = None # 用于存储当前打开的分卷文件对象,初始化为None
i = 1 # 分卷编号,从1开始计数
i = 1 # 这里重复赋值了,可能是笔误,不影响程序功能
2. 空白行处理标记
skip_blank_lines = False # 新增标记:是否正在跳过空白行,False表示不跳过
这个标记用于处理广告内容后面可能跟随的空白行,实现广告内容和其后续空白行的连续过滤。
3. 主循环:逐行处理文本
for line in file: # 遍历源文件的每一行stripped_line = line.strip() # 去除行首尾的空白字符(空格、换行符等),用于判断和匹配# 处理需要跳过空白行的情况if skip_blank_lines: # 如果处于跳过空白行状态if stripped_line == '': # 当前行是空白行continue # 跳过当前行,继续处理下一行else: # 当前行不是空白行skip_blank_lines = False # 关闭跳过空白行状态# 过滤广告内容if '手机电子书·大学生小说网' in stripped_line: # 如果当前行包含这个广告文本skip_blank_lines = True # 开启跳过空白行模式,处理广告后的空白行continue # 跳过当前广告行,不写入分卷文件# 处理分卷标记行if '卷 第' in stripped_line: # 如果当前行是分卷标记(如"卷 第一")# 生成分卷文件名,格式为"01_卷 第一.txt",确保编号是两位数juan_name = f"{i:02d}_{stripped_line}.txt"i += 1 # 分卷编号自增1# 创建分卷文件的完整路径,将分卷文件保存在"分卷"文件夹下path = os.path.join('分卷', juan_name)print(path) # 打印当前分卷文件的路径,方便查看进度# 关闭上一个分卷文件(如果存在)if flag == 1 and juan_file is not None: # 如果已经创建过分卷文件juan_file.close() # 关闭上一个分卷文件# 创建并打开当前分卷文件,用于写入内容juan_file = open(path, 'w', encoding='utf-8')flag = 1 # 更新标记,表示已经创建过分卷文件continue # 跳过当前分卷标记行,不写入分卷文件(也可以根据需要决定是否写入)# 写入内容到当前分卷文件if juan_file is not None: # 如果当前有打开的分卷文件juan_file.write(line) # 将当前行写入分卷文件(使用原始line而不是stripped_line,保留原始格式)
4. 清理工作:关闭文件
# 关闭最后一个分卷文件(如果存在)
if juan_file is not None:juan_file.close()# 关闭源文件
file.close()
代码的整体流程总结:
- 打开《红楼梦》源文件
- 逐行读取并处理内容:
- 遇到包含 "手机电子书・大学生小说网" 的广告行,跳过该行并忽略后续的空白行
- 遇到包含 "卷 第" 的分卷标记行,创建新的分卷文件(关闭上一个分卷文件)
- 其他内容行则写入当前打开的分卷文件
- 处理完成后,关闭所有打开的文件
代码的特点和作用:
- 自动分卷:根据文本中的 "卷 第 X" 标记自动创建多个分卷文件
- 广告过滤:去除包含特定广告内容的行及其后的空白行
- 格式保留:写入文件时使用原始行内容,保留了原文的格式和换行
- 路径处理:使用 os.path.join 处理路径,确保在不同操作系统上都能正常工作
- 安全处理:确保所有打开的文件最终都会被关闭,避免资源泄露
二、关键词提取
1. 导入必要的库
import pandas as pd # 用于数据处理和分析,这里主要用来构建DataFrame和处理停用词
import os # 用于文件和目录操作,遍历文件夹等
import jieba # 中文分词库,用于将中文文本分割成词语
2. 遍历文件夹收集文件路径和内容
# 初始化两个列表,分别存储文件路径和文件内容
filePaths = []
fileContents = []# 遍历"./分卷"目录下的所有文件(包括子目录中的文件)
# os.walk()返回一个三元组:当前目录路径、当前目录下的子目录列表、当前目录下的文件列表
for root, dirs, files in os.walk(r"分卷"):for name in files: # 遍历当前目录下的所有文件# 拼接完整的文件路径(根目录+文件名)filePath = os.path.join(root, name)filePaths.append(filePath) # 将文件路径添加到列表# 读取文件内容f = open(filePath, 'r', encoding='utf-8') # 以只读模式打开文件,指定编码为utf-8fileContent = f.read() # 读取整个文件内容f.close() # 关闭文件fileContents.append(fileContent) # 将文件内容添加到列表
3. 构建 DataFrame 存储数据
# 使用pandas构建一个数据框(类似表格),包含两列:filePath(文件路径)和fileContent(文件内容)
corpos = pd.DataFrame({'filePath': filePaths,'fileContent': fileContents
})
这一步将分散的文件路径和内容组织成结构化数据,方便后续批量处理。
4. 加载自定义资源
# 加载《红楼梦》专属分词补充词库,让jieba更好地识别小说中的专有名词(如人名、地名等)
jieba.load_userdict("红楼梦词库.txt")# 读取中文停用词表
# stopwordsCN.txt是包含中文停用词的文件(如"的"、"了"、"在"等无实际意义的词)
# encoding='utf8'指定编码,engine='python'避免编码相关的解析问题
# index_col=False表示不将任何一列作为索引
stopwords = pd.read_csv("stopwordsCN.txt", encoding='utf8', engine='python', index_col=False)
5. 分词处理与停用词过滤
# 打开一个文件用于写入分词结果
file_to_jieba = open('分词后汇总.txt', 'w', encoding='utf-8')# 遍历corpos数据框中的每一行(即每一卷的内容)
for index, row in corpos.iterrows():juan_ci = '' # 用于存储当前卷的分词结果fileContent = row['fileContent'] # 获取当前行的文件内容# 使用jieba进行分词,cut()方法返回一个可迭代的生成器segs = jieba.cut(fileContent)# 遍历每个分词结果for seg in segs:# 过滤条件:# 1. 该词不在停用词表中(seg not in stopwords.stopword.values)# 2. 去除空白字符后长度大于0(避免空字符串)if seg not in stopwords.stopword.values and len(seg.strip()) > 0:juan_ci += seg + ' ' # 将符合条件的词添加到结果字符串,并用空格分隔# 将当前卷的分词结果写入文件,每行对应一卷的内容file_to_jieba.write(juan_ci + '\n')# 关闭文件,释放资源
file_to_jieba.close()
代码整体流程总结:
- 收集数据:遍历 "分卷" 文件夹下的所有文件,获取它们的路径和内容
- 组织数据:用 DataFrame 将文件路径和内容关联起来,便于管理
- 准备工具:加载专业词库提升分词准确性,加载停用词表用于过滤无意义词汇
- 处理数据:对每一卷内容进行分词,过滤掉停用词和空字符串
- 保存结果:将处理后的分词结果写入 "分词后汇总.txt" 文件
代码的关键作用:
- 将原始文本转换为结构化的词语集合,为后续的文本分析(如词频统计、情感分析等)做准备
- 通过专业词库提高《红楼梦》这类特定文本的分词准确性
- 过滤停用词减少噪音,让分析更聚焦于有实际意义的词汇
- 保持卷与卷之间的结构,便于后续按卷进行对比分析
三、TF-IDF模拟
1. 导入必要的库
import pandas as pd # 用于数据处理和分析,构建DataFrame展示结果
from sklearn.feature_extraction.text import TfidfVectorizer # 从scikit-learn库导入TF-IDF向量器
TfidfVectorizer
是用于将文本转换为 TF-IDF 特征矩阵的工具,TF-IDF(词频 - 逆文档频率)是一种用于评估词语在文档集中重要性的统计方法。
2. 读取分词后的文本数据
# 打开分词后的汇总文件,读取所有行内容
infile = open('分词后汇总.txt','r',encoding='utf-8')
corpus = infile.readlines() # 读取文件所有行,存储为列表,每个元素对应一卷的分词结果
这里corpus
(语料库)是一个列表,假设分词后汇总.txt
中每行对应《红楼梦》的一卷,那么corpus
的每个元素就是一卷的分词文本。
3. 计算 TF-IDF 矩阵
# 初始化TF-IDF向量器
vectorizer = TfidfVectorizer()# 对语料库进行拟合(学习词汇表)并转换为TF-IDF矩阵
tfidf = vectorizer.fit_transform(corpus)# 获取词汇表(所有分词后的词语列表)
wordlist = vectorizer.get_feature_names() # 注意:在较新的sklearn版本中,建议使用get_feature_names_out()
fit_transform(corpus)
:完成两个操作,一是学习语料库中的所有词汇(构建词汇表),二是将每段文本转换为基于 TF-IDF 值的向量表示tfidf
是一个稀疏矩阵,形状为(文档数, 词汇数)
,每个元素表示某个词在某个文档中的 TF-IDF 值wordlist
是所有不重复词语的列表,顺序与 TF-IDF 矩阵的列对应
4. 构建 TF-IDF 数据框
# 将TF-IDF矩阵转置(词汇为行,文档为列),并转换为稠密矩阵,再构建DataFrame
df = pd.DataFrame(tfidf.T.todense(), index=wordlist)
tfidf.T
:将矩阵转置,原本是行 = 文档、列 = 词汇,转置后行 = 词汇、列 = 文档todense()
:将稀疏矩阵转换为稠密矩阵(适合小数据量,直观查看)- 最终
df
的结构:行索引是词语,列索引是文档编号,单元格值是该词在该文档中的 TF-IDF 值
5. 定义提取 Top N 关键词的函数
def get_top_keywords(col, top_n=10):# 过滤出当前文档(列)中TF-IDF值大于0的词语(即该词在文档中出现过)non_zero = col[col > 0]# 返回TF-IDF值最大的前top_n个词语及其值(按降序排列)return non_zero.nlargest(top_n).items()
col
表示 DataFrame 中的一列,对应一个文档(一卷)的所有词语的 TF-IDF 值non_zero
筛选出在当前文档中出现过的词语(TF-IDF>0)nlargest(top_n)
按值从大到小排序,取前top_n
个.items()
返回(词语, TF-IDF值)
的迭代器
6. 应用函数提取所有文档的关键词
# 对DataFrame的每一列(每个文档)应用get_top_keywords函数,提取前10个关键词
top_keywords_result = df.apply(lambda col: get_top_keywords(col, top_n=10),axis=0) # axis=0表示按列应用函数
top_keywords_result
是一个 Series,索引是文档编号,值是每个文档的前 10 个关键词及其 TF-IDF 值的迭代器
7. 打印结果
# 遍历结果,按文档编号(从1开始)打印每卷的核心关键词
for doc_idx, top_items in enumerate(top_keywords_result, start=1):print(f"第{doc_idx}回的核心关键词:{list(top_items)[:10]}")
enumerate(..., start=1)
生成从 1 开始的文档编号(对应第几卷)list(top_items)[:10]
将迭代器转换为列表,确保只取前 10 个关键词- 输出格式为 "第 X 回的核心关键词:[(词 1, 值 1), (词 2, 值 2), ...]"
代码整体流程总结:
- 数据输入:读取分词后的文本,构建语料库
- 特征提取:使用 TF-IDF 算法将文本转换为数值特征矩阵
- 数据整理:将 TF-IDF 矩阵转换为 DataFrame,方便按词语和文档查看
- 关键词提取:定义函数并应用到每个文档,提取 TF-IDF 值最高的前 10 个词
- 结果输出:按卷打印核心关键词及其 TF-IDF 值
关键概念解释:
- TF-IDF 值:综合考虑词语在当前文档中的出现频率(TF)和在所有文档中的出现频率(IDF),值越高表示该词在当前文档中越重要、越有代表性
- 核心关键词:TF-IDF 值高的词语,通常是该卷中出现较频繁且在其他卷中出现较少的特色词汇,能反映该卷的主要内容
四、泛用性
一、代码核心逻辑与可修改点
原代码流程可概括为:
原始文本收集→分卷 / 分块处理→分词与过滤→TF-IDF 关键词提取→结果输出
核心可修改点包括:
- 文本来源(输入文件 / 文件夹路径)
- 分块规则(按标记、长度、章节等)
- 分词补充词库(领域专属词汇)
- 停用词表(过滤无意义词汇)
- 关键词提取参数(Top N 数量、算法调整)
二、简单修改后的可能作用
-
文本结构化处理
通过修改分块规则(如按 “章节”“段落”“时间戳” 等标记),可将长文本拆分为结构化子文本,方便后续按单元分析。例如:将小说按 “章节” 拆分、将报告按 “小节” 拆分。 -
领域专属词汇提取
替换自定义词库(如将 “红楼梦词库.txt” 改为 “医学词库.txt”“法律词库.txt”)和停用词表,可精准识别领域内专业术语,过滤通用无意义词汇(如 “的”“在”)。 -
关键信息快速定位
调整 TF-IDF 参数(如修改top_n
数量、增加词语最小 / 最大出现频率限制),可提取每段文本的核心关键词,快速定位文本重点(如某章节的核心人物、某报告的核心观点)。 -
文本特征对比分析
通过输出各分块的关键词差异,可对比不同文本单元的内容侧重(如不同章节的主题变化、不同作者的写作风格差异)。
三、典型应用场景
1. 文学 / 历史文本分析
- 修改点:
- 分块规则:按 “回目”“章节标题” 拆分(如《三国演义》《史记》);
- 补充词库:添加古代人名、地名、官职专属词库(如 “丞相”“节度使”)。
- 作用:
提取每章节核心人物、事件关键词,分析情节发展脉络(如 “某章节关键词以‘战争’‘计谋’为主,反映军事主题”)。
2. 学术论文 / 报告整理
- 修改点:
- 分块规则:按 “摘要”“引言”“实验部分” 等标题拆分;
- 停用词表:添加学术通用虚词(如 “研究表明”“综上所述”)。
- 作用:
快速提取各部分核心术语(如实验方法、结论关键词),生成论文结构摘要。
3. 企业文档 / 客服记录分析
- 修改点:
- 文本来源:读取 “客服对话记录”“会议纪要” 文件夹;
- 分块规则:按 “日期”“对话 ID” 拆分单条记录;
- 补充词库:添加企业产品名、行业术语(如 “APP 闪退”“退款流程”)。
- 作用:
提取高频问题关键词(如 “登录失败”“物流延迟”),定位客户需求或业务痛点。
4. 社交媒体 / 舆情分析
- 修改点:
- 文本来源:读取 “微博评论”“论坛帖子” 文本文件;
- 停用词表:添加网络流行虚词(如 “哈哈哈”“绝了”)。
- 作用:
按时间段或话题分块,提取热点关键词(如某事件的讨论焦点),辅助舆情监控。
四、总结
这些代码本质是一套 “文本预处理 + 关键词提取” 的通用工具,通过修改分块规则、词库和输入来源,可快速适配文学、学术、企业、舆情等多领域的文本分析需求,核心价值是降低长文本处理成本,实现关键信息的自动化提取与对比。对于需要从大量文本中定位重点、分析主题变化的场景,具有较高的实用价值。