转载自:基于共现发现人物关系的python实现
作者:大邓【公众号:大邓和他的python】
要画出上图的节点网络关系图,需要使用Gephi,下载地址gephi,如果大家想精进学习gephi可以去这里学习https://www.baidu.com/link?url=a4REdia6AuOIP5ITsK6tf8Rs4kS9qr5YGT-sYIfKK4gMLHVjTtaiOg1q7iZi02yO&wd=&eqid=d15f436100054000000000065870a856
上面的步骤实际上很简单,都是可视化操作,照着鼠标点击gephi软件就可以,我就不展开了。但是使用gephi前,我们需要知道gephi软件需要的数据格式是什么样子的,只要准备好符合gephi的数据,才能出来绚丽的关系图。
画出绚丽的关系图,需要给gephi输入两份文件,即节点文件和边文件。
节点文件,有三个变量Id, Label, Weight(节点出现的次数)
边文件,有 Source(起点),Target(终端),Weight(该起点-终点的出现次数) 所以现在的问题是把上述的数据结构的两份文件(节点文件、边文件)准备好。节点文件还很好解决,只要统计出现的人物名的次数即可。
边文件里涉及到两个节点,及其出现的次数。这里就用到共现,即如果两个实体经常在一个区域出现,那么这两者存在关系的可能性会相当高。我们选择出现频率大于一定阈值的边,排除掉冗余的边,即可获取到边文件。
[文件及源码](https://pan.baidu.com/s/1geHFpa7)
import jieba
import codecs
import jieba.posseg as pseg
“”“
在代码中,我使用字典类型names保存人物,该字典的键为人物名称,值为该人物在全文中出现的次数。我使用字典类型relationships保存人物关系的有向边,该字典的键为有向边的起点,值为一个字典edge,edge的键是有向边的终点,值是有向边的权值,代表两个人物之间联系的紧密程度。lineNames是一个缓存变量,保存对每一段分词得到当前段中出现的人物名称,lineName[i]是一个列表,列表中存储第i段中出现过的人物。
”“”
names = {} # 姓名字典
relationships = {} # 关系字典
lineNames = [] # 每段内人物关系
# count names
# 加载字典
jieba.load_userdict("/Users/apple888/Desktop/桌面文件/project/釜行行/dict.txt")
with codecs.open("/Users/apple888/Desktop/桌面文件/project/釜山行/busan.txt", "r", "utf-8") as f:
for line in f.readlines():
# 分词并返回该词词性
poss = pseg.cut(line)
# 为新读入的一段添加人物名称列表
lineNames.append([])
for w in poss:
if w.flag != "nr" or len(w.word) < 2:
# 当分词长度小于2或该词词性不为nr时认为该词不为人名
continue
# 为当前段的环境增加一个人物
lineNames[-1].append(w.word)
if names.get(w.word) is None:
names[w.word] = 0
relationships[w.word] = {}
# 该人物出现次数加 1
names[w.word] += 1
# explore relationships
for line in lineNames:
# 对于每一段
for name1 in line:
# 每段中的任意两个人
for name2 in line:
if name1 == name2:
continue
if relationships[name1].get(name2) is None:
# 若两人尚未同时出现则新建项
relationships[name1][name2]= 1
else:
# 两人共同出现次数加 1
relationships[name1][name2] = relationships[name1][name2]+ 1
# output
with codecs.open("/Users/apple888/Desktop/桌面文件/project/釜山行/busan_node.txt", "a+", "utf-8") as f:
f.write("Id Label Weight\r\n")
for name, times in names.items():
f.write(name + " " + name + " " + str(times) + "\r\n")
with codecs.open("/Users/apple888/Desktop/桌面文件/project/釜山行/busan_edge.txt", "a+", "utf-8") as f:
f.write("Source Target Weight\r\n")
for name, edges in relationships.items():
for v, w in edges.items():
if w > 3:
f.write(name + " " + v + " " + str(w) + "\r\n")
之前在吴军《数学之美》提出过共现,但是不知道怎么实现,看了Foerc的这个实验,收获很大。想到了我之前做的文本情感分析,最基础的就是获得完整全面的情感词,但是不同领域的情感词是不同的,需要针对特定的领域进行针对性的建立词典。而这就需要用到共现理论,但之前苦于不懂如何实现。
欢迎公众号:大邓带你玩转python