数据分析案例-文本挖掘与中文文本的统计分析

简介: 数据分析案例-文本挖掘与中文文本的统计分析

项目背景介绍

       四大名著,又称四大小说,是汉语文学中不可多得的作品。这四部著作历久不衰,其中的故事、场景,已经深深地影响了国人的思想观念、价值取向。四部著作都有很高的艺术水平,细致的刻画和所蕴含的思想都为历代读者所称道。


       本次将以小说HLM为例,介绍中文文本的统计分析和文本发掘等方面的基本知识。


数据准备

关于小说内容,读者可自行搜集。


项目流程

1.读取小说内容

# 获取HLM文本数据
with open('HLM.txt','r',encoding='utf-8')as f:
    text = f.read()

2.统计词频

import jieba
# 分词并统计词频
def wordFreq(text,topn):
    words = jieba.lcut(text.strip()) # 对文本进行分词操作
    counts = {}
    for word in words:  # 统计每个词出现的频率,存放在字典counts中
        if len(word) == 1:  # 如果该词的长度为1,则跳过,不参与统计。
            continue
        counts[word] = counts.get(word,0) + 1
    items = list(counts.items())
    items.sort(key=lambda x:x[1],reverse=True)  # 按照词频进行排序
    f = open('HLM_词频.txt','w',encoding='utf-8')
    for i in range(topn):  # topn表示要取的词的个数,将频率最高的topn个词及其频率数存放在文件中
        word,count = items[i]
        f.writelines("{}\t{}\n".format(word,count))
    f.close() 
wordFreq(text,20)  # 这里我们提取出频率最高的前20个词



出现频率最高的词语是“宝玉”,出现了3772次,宝玉当仁不让的是《HLM》的一号主角。后面紧跟的高频词是“什么”,“一个”,这些也都是无意义的词语,需要我们进一步去除。


3.去除停用词

这里我们只需要加载停用词库,统计词频的时候加上判断即可。

# 分词并统计词频
def wordFreq(text,topn):
    words = jieba.lcut(text.strip()) # 对文本进行分词操作
    # 加载停用词库
    stopwords = [line.strip() for line in open('停用词库.txt','r',encoding='utf-8').readlines()]
    counts = {}
    for word in words:  # 统计每个词出现的频率,存放在字典counts中
        if len(word) == 1:  # 如果该词的长度为1,则跳过,不参与统计。
            continue
        elif word not in stopwords:  # 如果该词不在停用词列表stopwords中,才参与统计
            counts[word] = counts.get(word,0) + 1
    items = list(counts.items())
    items.sort(key=lambda x:x[1],reverse=True)  # 按照词频进行排序
    f = open('HLM_词频.txt','w',encoding='utf-8')
    for i in range(topn):  # topn表示要取的词的个数,将频率最高的topn个词及其频率数存放在文件中
        word,count = items[i]
        f.writelines("{}\t{}\n".format(word,count))
    f.close() 


观察输出结果,不难发现“凤姐”和“凤姐儿”应该是一个人物,包括后面的“黛玉”和“林黛玉”,“林妹妹”也是一个人,“宝玉”以及“宝二爷”也应该一起统计。


所以我们还需要处理小说中同一人物,不同称呼的情况。对上面的代码进行改进。


# 分词并统计词频
def wordFreq(text,topn):
    words = jieba.lcut(text.strip()) # 对文本进行分词操作
    # 加载停用词库
    stopwords = [line.strip() for line in open('停用词库.txt','r',encoding='utf-8').readlines()]
    counts = {}
    for word in words:  # 统计每个词出现的频率,存放在字典counts中
        if len(word) == 1:  # 如果该词的长度为1,则跳过,不参与统计。
            continue
        elif word not in stopwords:  # 如果该词不在停用词列表stopwords中,才参与统计
            if word == '凤姐儿':
                word = '凤姐'
            elif word == '林黛玉' or word == '林妹妹':
                word = '黛玉'
            elif word == '二爷':
                word = '宝玉'
            counts[word] = counts.get(word,0) + 1
    items = list(counts.items())
    items.sort(key=lambda x:x[1],reverse=True)  # 按照词频进行排序
    f = open('HLM_词频.txt','w',encoding='utf-8')
    for i in range(topn):  # topn表示要取的词的个数,将频率最高的topn个词及其频率数存放在文件中
        word,count = items[i]
        f.writelines("{}\t{}\n".format(word,count))
    f.close() 


4.绘制词云图

这里我们调用获取词频函数,获取TOP500,最后绘制词云图


# 绘制词云
import matplotlib.pyplot as plt
import wordcloud
import imageio
wordFreq(text,500)  # 获取TOP500的词频
word_cloud_text = open('HLM_词频.txt','r',encoding='utf-8').read()
bg_pic = imageio.imread('star.jpg') # 读入形状图片
wc = wordcloud.WordCloud(font_path=r'C:\Windows\Fonts\simhei.ttf',
                            background_color='white',
                            width=1000,
                            max_words=200,
                            mask=bg_pic,  # mask参数设置词云形状
                            height=860,
                            margin=2
                            ).generate(word_cloud_text)
wc.to_file('HLMcloud_star.png')  # 保存图片



5.章回处理

导入Python中的正则表达式(re模块),通过正则匹配,找到文中所有“第**回”形式的字符。“\u4e00”和“\u9fa5”是unicode编码,并且正好是中文编码的开始和结束的两个值,所以这个正则表达式可以用来判断字符串中是否包含中文。

# 章回处理
import re
chapter = re.findall('第[\u4e00-\u9fa5]+回',text)
lst_chapter = []
for x in chapter:  # 去除重复的章节
    if x not in lst_chapter and len(x)<=5:
        lst_chapter.append(x)
print(lst_chapter)


获取每一回起始和结束数据

lst_start_chapterIndex = []
for x in lst_chapter:  # 找出每一回在原文中的起始位置
    lst_start_chapterIndex.append(text.index(x))
lst_end_chapterIndex = lst_start_chapterIndex[1:]+[len(text)]  # 找出每一回在原文中的结束位置,本回的结束位置就是下一回的起始位置。最后一回的结束位置就是全文的结束。zip将每一回的起始和结束位置拼成一个元组,存放在lst_chapterindex列表中。
lst_chapterIndex = list(zip(lst_start_chapterIndex,lst_end_chapterIndex))
print(lst_chapterIndex)

5.1HLM之“刘姥姥三进荣国府”


统计在每一回中刘姥姥的出场次数并用折线图可视化。


# 统计刘姥姥出现的次数
cnt_liulaolao = []
for i in range(120):
    start = lst_chapterIndex[i][0]
    end = lst_chapterIndex[i][1]
    cnt_liulaolao.append(text[start:end].count('刘姥姥'))
plt.rcParams['font.sans-serif'] = ['SimHei'] #解决中文显示
plt.rcParams['axes.unicode_minus'] = False   #解决符号无法显示
plt.figure(figsize=(15,6))
plt.plot(range(120),cnt_liulaolao,label='刘姥姥出场次数')
plt.title('《HLM》——刘姥姥三进荣国府',fontdict={'fontsize':14})
plt.xlabel('章节数',fontdict={'fontsize':14})
plt.ylabel('出现次数',fontdict={'fontsize':14})
plt.legend()
plt.show()



5.2HLM之“哭说笑闹总关情”  


       我们尝试分析一下在小说的每一回里,“笑”和“喜”,“哭”与“悲”分别出现的次数,能不能通过这样一个小小的切入点,看一看贾府的兴衰与荣辱变化。统计每一回中“笑”和“喜”,“哭”与“悲”的出现次数。 并用折线图可视化。


# 统计情绪次数
cnt_laugh = []
cnt_cry = []
for i in range(120):
    start = lst_chapterIndex[i][0]
    end = lst_chapterIndex[i][1]
    cnt_laugh.append(text[start:end].count('笑')+text[start:end].count('喜'))
    cnt_cry.append(text[start:end].count('哭')+text[start:end].count('悲'))
# 可视化
plt.figure(figsize=(15,6))
plt.plot(range(120),cnt_laugh,label='笑和喜')
plt.plot(range(120),cnt_cry,label='哭和悲')
plt.title('《HLM》120回悲喜变化图',fontdict={'fontsize':14})
plt.xlabel('章节数',fontdict={'fontsize':14})
plt.ylabel('出现次数',fontdict={'fontsize':14})
plt.legend()
plt.show()


5.3HLM之平均段落数与字数


统计每一章段落数和字数并可视化。

cnt_chap = []  # 存放每一回的段落数
cnt_word = []  # 存放每一回的字符总数
for i in range(120):
    start = lst_chapterIndex[i][0]
    end = lst_chapterIndex[i][1]
    cnt_chap.append(text[start:end].count('\n'))
    cnt_word.append(len(text[start:end]))
# 可视化
plt.figure(figsize=(15,8))
plt.scatter(cnt_chap,cnt_word)
for i in range(120):
    plt.text(cnt_chap[i]-2,cnt_word[i]+100,lst_chapter[i],size=7)
plt.xlabel('章节段数',fontdict={'fontsize':14})
plt.ylabel('章节字数',fontdict={'fontsize':14})
plt.title('《HLM》120回',fontdict={'fontsize':14})
plt.show()



5.4HLM之人物社交关系网络


提取小说中的人名


分析人物关系,首先我们需要将书中涉及到的人物姓名提取出来。我们利用在之前生成的词频文件,抽取排名靠前的二十四个人物,研究他们之间的社交关系情况。简便起见,将这些人物名称存放在列表Names中。

Names=['宝玉','凤姐','贾母','黛玉','王夫人','老太太','袭人','贾琏','平儿','宝钗','薛姨妈','探春','鸳鸯','贾政','晴雯','湘云','刘姥姥','邢夫人','贾珍','紫鹃','香菱','尤氏','薛蟠','贾赦']

基于共现关系获取人物关系权重


一般我们认为,在一篇文章中的同一段出现的两个人物之间,一定具有某种关联,因此我们将每一段中的人物角色抽取出来,然后以段落为单位,统计两个角色同时出现的共现次数,并把结果存在一个二维矩阵之中。

Names=['宝玉','凤姐','贾母','黛玉','王夫人','老太太','袭人','贾琏','平儿','宝钗','薛姨妈','探春','鸳鸯','贾政','晴雯','湘云','刘姥姥','邢夫人','贾珍','紫鹃','香菱','尤氏','薛蟠','贾赦']
relations = {}
lst_para = text.split('\n')  # 按段落划分,假设在同一段落中出现的人物具有共现关系
for t in lst_para:
    for name1 in Names:
        if name1 in t:
            for name2 in Names:
                if name2 in t and name1 != name2 and (name2,name1) not in relations:
                    relations[(name1,name2)] = relations.get((name1,name2),0)+1
print(relations.items())


接下来对权重值做归一化操作,找到共现次数的最大值,然后将所有的共现次数映射到0-1之间。

maxRela = max([v for k,v in relations.items()])
relations = {k:v/maxRela for k,v in relations.items()}
print(relations)

绘制人物社交网络图


使用networkx库,绘制人物社交网络图。


import networkx as nx
plt.figure(figsize=(12,12))
G= nx.Graph()
# 根据relations的数据向G中添加边
for k,v in relations.items():
    G.add_edge(k[0],k[1],weight=v)
elarge = [(u,v)for (u,v,d) in G.edges(data=True) if d['weight']>0.6]
emidle = [(u,v)for (u,v,d) in G.edges(data=True) if (d['weight']>0.3)&(d['weight']<=0.6)]
esmall = [(u,v)for (u,v,d) in G.edges(data=True) if d['weight']<=0.3]
# 设置图形布局
pos = nx.spring_layout(G)
# 设置节点样式
nx.draw_networkx_nodes(G,pos,alpha=0.8,node_size=800)
nx.draw_networkx_edges(G,pos,edgelist=elarge,width=2.5,alpha=0.9,edge_color='g')
nx.draw_networkx_edges(G,pos,edgelist=emidle,width=1.5,alpha=0.6,edge_color='r')
nx.draw_networkx_edges(G,pos,edgelist=esmall,width=1,alpha=0.4,edge_color='b',style='dashed')
nx.draw_networkx_labels(G,pos,font_size=12)
plt.axis('off')
plt.title('《HLM》主要人物社交关系网络图')
plt.show()


emmm,这个风格好像有点不太好看,我们换个风格。


plt.figure(figsize=(8,6))
pos = nx.circular_layout(G)
# 设置节点样式
nx.draw_networkx_nodes(G,pos,alpha=0.6,node_size=800)
nx.draw_networkx_edges(G,pos,edgelist=elarge,width=2.5,alpha=0.9,edge_color='g')
nx.draw_networkx_edges(G,pos,edgelist=emidle,width=1.5,alpha=0.6,edge_color='r')
nx.draw_networkx_edges(G,pos,edgelist=esmall,width=1,alpha=0.2,edge_color='b',style='dashed')
nx.draw_networkx_labels(G,pos,font_size=12)
plt.axis('off')
plt.title('《HLM》主要人物社交关系网络图')
plt.show()

绿色权值最大,代表关系越深;红色权值处于中间,关系一般;蓝色权值最低,关系较弱。


从关系图中,我们可以看出贾宝玉社交关系又多又深,不愧是小说中的主角,社交广泛。


好了,以上就是本次分享的项目案例,如果对读者有所帮助,那就留下你的三连吧。



目录
相关文章
|
9月前
|
数据可视化 数据挖掘
R语言生存分析数据分析可视化案例(下)
R语言生存分析数据分析可视化案例
|
6月前
|
数据采集 存储 数据挖掘
【优秀python数据分析案例】基于Python书旗网小说网站数据采集与分析的设计与实现
本文介绍了一个基于Python的书旗网小说网站数据采集与分析系统,通过自动化爬虫收集小说数据,利用Pandas进行数据处理,并通过Matplotlib和Seaborn等库进行数据可视化,旨在揭示用户喜好和市场趋势,为图书出版行业提供决策支持。
505 6
【优秀python数据分析案例】基于Python书旗网小说网站数据采集与分析的设计与实现
|
2月前
|
机器学习/深度学习 数据采集 DataWorks
数据分析经典案例重现:使用DataWorks Notebook 实现Kaggle竞赛之房价预测,成为数据分析大神!
Python是目前当之无愧的数据分析第一语言,大量的数据科学家使用Python来完成各种各样的数据科学任务。本文以Kaggle竞赛中的房价预测为例,结合DataWorks Notebook,完成数据加载、数据探索、数据可视化、数据清洗、特征分析、特征处理、机器学习、回归预测等步骤,主要Python工具是Pandas和SKLearn。本文中仅仅使用了线性回归这一最基本的机器学习模型,读者可以自行尝试其他更加复杂模型,比如随机森林、支持向量机、XGBoost等。
|
4月前
|
机器学习/深度学习 并行计算 数据挖掘
R语言是一种强大的统计分析工具,广泛应用于数据分析和机器学习领域
【10月更文挑战第21天】R语言是一种强大的统计分析工具,广泛应用于数据分析和机器学习领域。本文将介绍R语言中的一些高级编程技巧,包括函数式编程、向量化运算、字符串处理、循环和条件语句、异常处理和性能优化等方面,以帮助读者更好地掌握R语言的编程技巧,提高数据分析的效率。
94 2
|
6月前
|
数据采集 数据可视化 关系型数据库
【优秀python 数据分析案例】基于python的穷游网酒店数据采集与可视化分析的设计与实现
本文介绍了一个基于Python的穷游网酒店数据采集与可视化分析系统,通过爬虫技术自动抓取酒店信息,并利用数据分析算法和可视化工具,提供了全国主要城市酒店的数量、星级、价格、评分等多维度的深入洞察,旨在为旅行者和酒店经营者提供决策支持。
210 4
【优秀python 数据分析案例】基于python的穷游网酒店数据采集与可视化分析的设计与实现
|
6月前
|
JSON 数据挖掘 API
案例 | 用pdpipe搭建pandas数据分析流水线
案例 | 用pdpipe搭建pandas数据分析流水线
63 2
|
6月前
|
数据采集 存储 数据可视化
【优秀python数据分析案例】基于python的中国天气网数据采集与可视化分析的设计与实现
本文介绍了一个基于Python的中国天气网数据采集与可视化分析系统,通过requests和BeautifulSoup库实现数据爬取,利用matplotlib、numpy和pandas进行数据可视化,提供了温湿度变化曲线、空气质量图、风向雷达图等分析结果,有效预测和展示了未来天气信息。
1971 3
|
6月前
|
数据采集 数据可视化 数据挖掘
【优秀python案例】基于python爬虫的深圳房价数据分析与可视化实现
本文通过Python爬虫技术从链家网站爬取深圳二手房房价数据,并进行数据清洗、分析和可视化,提供了房价走势、区域房价比较及房屋特征等信息,旨在帮助购房者更清晰地了解市场并做出明智决策。
259 2
|
6月前
|
数据采集 数据可视化 算法
基于Python flask的boss直聘数据分析与可视化系统案例,能预测boss直聘某个岗位某个城市的薪资
本文介绍了一个基于Python Flask框架的Boss直聘数据分析与可视化系统,系统使用selenium爬虫、MySQL和csv进行数据存储,通过Pandas和Numpy进行数据处理分析,并采用模糊匹配算法进行薪资预测。
162 0
基于Python flask的boss直聘数据分析与可视化系统案例,能预测boss直聘某个岗位某个城市的薪资
|
7月前
|
数据采集 机器学习/深度学习 数据可视化
完整的Python数据分析流程案例解析-数据科学项目实战
【7月更文挑战第5天】这是一个Python数据分析项目的概览,涵盖了从CSV数据加载到模型评估的步骤:获取数据、预处理(处理缺失值和异常值、转换数据)、数据探索(可视化和统计分析)、模型选择(线性回归)、训练与评估、优化,以及结果的可视化和解释。此流程展示了理论与实践的结合在解决实际问题中的应用。
154 1