当前位置: 首页 > 科技观察

震惊!用Python探索《红楼梦》的人物关系!_0

时间:2023-03-23 10:09:18 科技观察

资料准备红楼梦txt电子书。金陵十二姬+贾宝玉人物名表。宝玉nr黛玉nr宝钗nr湘云nr奉节nr李婉儿nr元春nr迎春nr探春nr惜春nr妙玉nr巧姐nr秦氏nr此子表是分词的,后面的nr是人名的意思。先看小说人物出现次数;withopen("红楼梦.txt",encoding="gb18030")asf:honglou=f.read()接下来整理出场数据;honglou=honglou.replace("\n","")honglou_new=honglou.split("")renwu_list=['宝玉','黛玉','宝钗','祥云','凤姐','李婉','元春','迎春','探春','惜春','妙玉','巧姐','秦氏']renwu=pd.DataFrame(data=renwu_list,columns=['name'])renwu['Occurrences']=renwu.apply(lambdax:len([kforkinhonglou_newifx[u'name']ink]),axis=1)renwu.to_csv('renwu.csv',index=False,sep=',')renwu.sort_values('出现次数',ascending=False,inplace=True)attr=renwu['name'][0:12]v1=renwu['出现次数'][0:12】这样我们得到了attr和v1的两条数据,内容如下:接下来我们可以使用pyecharts绘制直方图;bar=(Bar().add_xaxis(attr.tolist()).add_yaxis("上镜时代",v1.tolist()).set_global_opts(title_opts=opts.TitleOpts(title="红楼梦上镜13")))bar.render_notebook()人物关系数据处理我们先对读入内存的小说内容进行jieba分词;importjiebajieba.load_userdict("renwu_forcut")renwu_data=pd.read_csv("renwu_forcut",header=-1)mylist=[k[0].split("")[0]forkinrenwu_data.values.tolist()]通过load_userdict加载我们上面自定义的字典到jieba库中;接下来的分词处理;tmpNames=[]names={}relationships={}forhinhonglou:h.replace("贾妃","元春")h.replace("李恭才","李婉")poss=pseg.cut(h)tmpNames.append([])forwinposs:ifw.flag!='nr'orlen(w.word)!=2orw.wordnotinmylist:continuetmpNames[-1].append(w.word)ifnames.get(w.word)isNone:names[w.word]=0relationships[w.word]={}names[w.word]+=1因为“贾贵妃”的名字、“元春”、“李公才”、“李万”等文本中的字符混淆严重,所以这里进行替换处理后,使用jieba库提供的pseg工具进行分词,会返回每个单词的词性。经过判断后,只有符合要求且在我们提供的词典列表中的分词才会被保留。每出现一个人,就会增加一个,方便后面画关系图的时候确定人物节点的大小。对于存在于我们的自定义词典中的人名,将它们保存在一个临时变量tmpNames中。以下处理每个段落中字符之间的关系:fornameintmpNames:forname1inname:forname2inname:ifname1==name2:continueifrelationships[name1].get(name2)isNone:relationships[name1][name2]=1else:relationships[name1][name2]+=1对于出现在同一段落中的字符,我们认为它们是密切相关的,每出现一次,关系就增加1。最后,相关的信息可以保存到文件中。withopen("relationship.csv","w",encoding='utf-8')asf:f.write("Source,Target,Weight\n")forname,edgesinrelationships.items():对于v,winedges.items():f.write(name+","+v+","+str(w)+"\n")withopen("NameNode.csv","w",编码='utf-8')asf:f.write("ID,Label,Weight\n")forname,timesinnames.items():f.write(name+","+name+","+str(times)+"\n")文件1:角色关系表,包括先出现的角色、后出现的角色以及一起出现的次数。文件2:字符比例表,包括字符出现的总次数,出现次数越多,所占比例越大。数据分析接下来,我们可以做一些简单的人物关系分析。这里我们还是使用pyecharts来绘制图表。defdeal_graph():关系数据=pd.read_csv('relationship.csv')namenode_data=pd.read_csv('NameNode.csv')relationship_data_list=relationship_data.values.tolist()namenode_data_list=namenode_data.values.tolist()nodes=[]fornodeinnamenode_data_list:ifnode[0]=="Baoyu":node[2]=node[2]/3nodes.append({"name":node[0],"symbolSize":node[2]/30})links=[]forlinkinrelationship_data_list:links.append({"source":link[0],"target":link[1],"value":link[2]})g=(Graph().add("",nodes,links,repulsion=8000).set_global_opts(title_opts=opts.TitleOpts(title="红楼人物关系")))returng首先通过pandas将这两个文件读入内存。对于“宝玉”,因为它的比例太大,如果统一缩放,其他角色的节点太小,显示不美观,所以这里先做一个缩放。最后得到人物关系图如下: