【Python】构建关键词共现矩阵完整版

这篇博客介绍了如何使用Python构建关键词共现矩阵,包括一个完整的代码框架,经过优化后显著提高了速度,并解决了空关键词问题。代码示例分别基于numpy和list实现,最终提供了一个整合的终版代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有个网友写了一个帖子叫做:

python构建关键词共现矩阵,里面构造了完整的代码框架,可测试,有两个版本(numpy版和list版可用)。优点是完整可测试,缺点是速度较慢。

后来有网友改进了这个代码:

python构建关键词共现矩阵速度优化,里面对代码进行了优化,优点是能把几个小时能优化到3分钟,缺点是只贴出一部分代码。

我综合了这两个人的代码,构造出一个终版可用的版本。优点有:无需导入原始依赖的reader函数、速度快、可运行、去除了空关键词。代码如下:

# -*- coding: utf-8 -*-
# @ChangedDate    : 2021-07-15 19:23:00
# @Author  : Alan Lau (rlalan@outlook.com)
import numpy as np
import time
from pprint import pprint as p


def log(func):
    def wrapper(*args, **kwargs):
        now_time = str(time.strftime('%Y-%m-%d %X', time.localtime()))
        print('------------------------------------------------')
        print('%s func [%s] called' % (now_time, func.__name__))
        print('# %s' % func.__doc__)
        print('%s returns:' % func.__name__)
        re = func(*args, **kwargs)
        p(re)
        return re
    return wrapper


def readxls(path):
    import xlrd
    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])


@log
def get_set_key(data, threshold=2):
    '''选取频数大于等于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}
    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


@log
def format_data(data, set_key_list):
    '''格式化需要计算的数据,将原始数据格式转换成二维数组'''
    formated_data = []
    for ech in data:
        ech_line = ech.split('/')

        temp=[]            # 筛选出format_data中属于关键词集合的词
        for e in ech_line:
            if e in set_key_list:
                temp.append(e)
        ech_line=temp

        ech_line = list(set(filter(lambda x: x != '', ech_line))) #set去掉重复数据
        formated_data.append(ech_line)
    return formated_data


@log
def build_matirx(set_key_list):
    '''建立矩阵,矩阵的高度和宽度为关键词集合的长度+1'''
    edge = len(set_key_list)+1
    # matrix = np.zeros((edge, edge), dtype=str)
    matrix = [[0 for j in range(edge)] for i in range(edge)]
    return matrix


@log
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

@log
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 main():
    keyword_path = r'test.xlsx'
    output_path = r'2.txt'
    data = readxls(keyword_path)
    set_key_list = get_set_key(data)
    formated_data = format_data(data, set_key_list)
    matrix = build_matirx(set_key_list)
    matrix = init_matrix(matrix, set_key_list)
    result_matrix = count_matrix(matrix, formated_data)
    np.savetxt(output_path, result_matrix, fmt=('%s,'*len(matrix))[:-1])



if __name__ == '__main__':
    main()

test.xlsx内容如下:

最后,还有一位网友贴出了一个“属性共现”的改进代码,见关键词共现/属性共现矩阵

 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值