【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内容如下:

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

 

### 构建专利主体合作矩阵矩阵的方法 构建专利主体合作矩阵矩阵的核心在于识别和量化不同专利主体(如发明人、机构、公司等)之间的合作关系或频率。以下是详细的说明和技术实方式: #### 数据准备 为了构建合作矩阵矩阵,首先需要从原始专利数据中提取必要的信息。这些信息通常包括但不限于以下几类: - **专利编号**:唯一标识每一项专利。 - **申请人/发明人信息**:这是构建合作矩阵的主要对象,可以是个人姓名、企业名称或研究机构名称。 - **申请日期**:有助于时间序列分析。 - **技术领域**:通过国际专利分类(IPC)、关键词等方式描述专利的主题。 通过对上述信息的整理,可以获得一个结构化的数据集,其中每条记录对应一项专利及其相关联的主体信息[^1]。 #### 合作关系定义 在专利语境下,“合作”通常指同一项专利由多个主体同完成的情形。因此,合作关系可以通过以下几种方式进行定义: - **直接合作**:如果某两项专利具有完全相同的申请人或发明人名单,则认为这两个主体之间存在直接的合作关系。 - **间接合作**:即使两个主体并未直接参与同一件专利的研发工作,但如果他们分别与其他同参与者有过交集,则也可以视为一种广义上的间接合作关系。 #### 矩阵构建过程 接下来介绍如何基于前述准备工作来实际生成所需的合作矩阵矩阵: ##### 方法一:二部图投影法 假设我们已经得到了一份包含所有专利及其相应贡献者的清单。那么就可以将其转化为一张无向加权图G=(V,E),其中顶点集合V代表各个独立的个体单位(即潜在合作者), 而边e(u,v)∈E则表示两者曾经至少联合提交过一次申请,并赋予该连接一定的权重w(e)=f(|S|),这里的函数f()可以根据实际情况灵活调整——例如取值为同拥有的项目总数目或者仅记为布尔型标志位1/0而已. 随后应用社会网络分析理论中的双模态转换技巧(bipartite projection technique)[^2], 我们可以从初始状态下的异质性关联模式出发推导出最终版本内的均质化表达形式—也就是目标意义上的单层协作度量表征结果M=[m_ij]. 具体计算公式如下所示: \[ m_{ij} = \begin{cases} \sum_k w(k,i)*w(k,j)/d_i & \text{if } i \neq j \\ 0 & \text{otherwise}. \end{cases}\] 此处,d_i指的是节点i总的邻居数量; k迭代范围覆盖整个中间媒介层元素k属于K={...}; 权重因子w(x,y)反映了任意一对相连实体xy间亲密程度高低差异状况. ##### 方法二:频次统计法 另一种更为直观简单的做法便是单纯依赖历史积累下来的实证统计数据来进行归纳总结. 即先按照既定规则筛选符合条件的目标群体样本库Q, 接着逐一扫描遍历每一个案例实例c_q(q=1,...,n_Q), 对于每次遇到的新配对组合(p,q)_t都会更新累加器counter[p][q]+=1直至结束为止. 最终获得的结果就是期望得到的那个稀疏分布式的邻接表格T=[[t_11,t_12,...],[t_21,t_22,...],...] ```python import numpy as np from itertools import combinations def create_collaboration_matrix(patent_records): ''' 创建专利主体合作矩阵 参数: patent_records (list of dict): 每一条记录是一个字典,键包括'patent_id', 'inventors' 返回: collaboration_matrix (np.ndarray): 主体间的合作次数构成的矩阵 ''' all_entities = set() for record in patent_records: entities = tuple(record['inventors']) # 假设'inventors'字段保存了一个列表 all_entities.update(entities) entity_to_index = {entity:i for i,entity in enumerate(sorted(all_entities))} num_entities = len(entity_to_index) collab_mat = np.zeros((num_entities,num_entities)) for record in patent_records: inventors = record['inventors'] pairs = list(combinations(inventors, r=2)) for p,q in pairs: idx_p,idx_q = sorted([entity_to_index[p],entity_to_index[q]]) collab_mat[idx_p,idx_q] +=1 return collab_mat + collab_mat.T - np.diag(np.diagonal(collab_mat)) # 示例输入数据 sample_data = [ {'patent_id':'US9876543B2','inventors':['Alice','Bob']}, {'patent_id':'CN1234567A','inventors':['Charlie','David','Eve']}, ... ] collaboration_matrix = create_collaboration_matrix(sample_data) print(collaboration_matrix) ``` --- #### 注意事项 在执行以上操作时需要注意几个关键点: - 数据清洗的重要性不可忽视,尤其是针对那些可能存在拼写错误或是缩写的名称部分更要格外小心谨慎对待; - 隐私保护政策可能会限制公开可用资源里的个人信息披露程度,所以在设计解决方案之初就应该考虑到这一因素的影响; ---
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值