金庸小说人物知识图谱构建——构建共现矩阵

利用上一步得到的共现人物共现关系excel表,构建人物间的共现矩阵,如下图
金庸小说人物知识图谱构建——构建共现矩阵_第1张图片
两两人物间的数字对应他们的共现频次,代表他们在多少个章节中共同出现了,对角线上的频次定义为0,共现频次越高,人物间的关系可能越紧密。

这里贴出代码

#构建共现矩阵
import numpy as np
from numpy.matrixlib.defmatrix import matrix
import xlrd

def readxls(path):
    xl = xlrd.open_workbook(path)
    sheet = xl.sheets()[0]
    data = []
    for i in range(0,sheet.ncols):
        data.append(list(sheet.col_values(i)))#添加
    return (data[0])#返回第一列

def get_set_key(data, threshold = 1):
    '''选取频数大于等于Threshold的关键词构建一个集合,用于作为共现矩阵的首行和首列'''
    all_key = '/'.join(data)
    key_list = [it.strip() for it in all_key.strip().split('/')]
    keys = set(key_list)
    dic = dict(zip(keys, [key_list.count(k) for k in keys]))#关键词以及出现次数的字典

    wf = {k: v for k, v in dic.items() if k != ' ' and v >= threshold}#选取频数大于等于Threshold的关键词
    set_key_list = []
    for a in sorted(wf.items(), key = lambda item: item[1], reverse = True):#降序排列
         set_key_list.append(a[0])
    return set_key_list

def format_data(data):
    '''格式化需要计算的数据,将原始数据格式转换成二维数组'''
    formated_data = []
    for ech in data:
        ech_line = ech.split('/')
        formated_data.append(ech_line)
    return formated_data
# def dic(data):#关键词字典
#     keytxt = '/'.join(data)
#     keyfir = keytxt.split('/')
#     keylist = list(set([key for key in keyfir if key != '']))
#     keydic = {}
#     pos = 0
#     for i in keylist:
#         pos = pos+1
#         keydic[pos] = str(i)
#     return keydic
def build_matirx(set_key_list):
    '''建立矩阵,矩阵的高度和宽度为关键词集合的长度+1'''
    edge = len(set_key_list)+1
    # matrix = np.zeros((edge, edge), dtype=str)
    matrix = [['' for j in range(edge)] for i in range(edge)]
    return matrix

def init_matrix(matrix, set_key_list):
    '''初始化矩阵,将关键词集合赋值给第一列和第二列'''
    matrix[0][1:] = np.array(set_key_list)
    matrix = list(map(list, zip(*matrix)))
    matrix[0][1:] = np.array(set_key_list)
    return matrix

def count_matrix(matrix, formated_data):
    '''计算各个关键词共现次数'''
    keywordlist=matrix[0][1:]  #列出所有关键词
    appeardict={}  #每个关键词与 [出现在的行(formated_data)的list] 组成的dictionary
    for w in keywordlist:
        appearlist=[]
        i=0
        for each_line in formated_data:
            if w in each_line:
                appearlist.append(i)
            i +=1
        appeardict[w]=appearlist#某个关键词出现在哪一行
    for row in range(1, len(matrix)):
        # 遍历矩阵第一行,跳过下标为0的元素
        for col in range(1, len(matrix)):
                # 遍历矩阵第一列,跳过下标为0的元素
                # 实际上就是为了跳过matrix中下标为[0][0]的元素,因为[0][0]为空,不为关键词
            if col >= row:
                #仅计算上半个矩阵
                if matrix[0][row] == matrix[col][0]:
                    # 如果取出的行关键词和取出的列关键词相同,则其对应的共现次数为0,即矩阵对角线为0
                    matrix[col][row] = 0
                else:
                    counter = len(set(appeardict[matrix[0][row]])&set(appeardict[matrix[col][0]]))#两个集合取交集
 
                    matrix[col][row] = counter
            else:
                matrix[col][row]=matrix[row][col]
    return matrix
#归一化
def normalization(matrix):
    sum=0
    for row in range(1,len(matrix[0])):
        for col in range (1,len(matrix[0])):
            sum+=matrix[row][col]
    for row in range(1,len(matrix[0])):
        for col in range (1,len(matrix[0])):
            matrix[row][col]=round(matrix[row][col]/sum,6)
    return matrix

def main():
    keyword_path = r'D:xxxxxxx/雪山飞狐共现人名.xlsx'
    output_path = r'D:xxxxxxxx/雪山飞狐_matrix.txt'
    data = readxls(keyword_path)
    set_key_list = get_set_key(data,1)
    formated_data=format_data(data)
    matrix=build_matirx(set_key_list)
    initial_matrix=init_matrix(matrix,set_key_list)
    result_matrix=count_matrix(initial_matrix,formated_data)
    #normalized_matrix=normalization(result_matrix)#归一化后的矩阵
    np.savetxt(output_path, np.c_[result_matrix], fmt='%s',delimiter='\t')
    #print(normalized_matrix)

if __name__ == '__main__':
    main()

注意:
代码里有文件路径需要改成自己的

参考文章
这里

你可能感兴趣的:(知识图谱,知识图谱,矩阵,人工智能)