基于Pandas构建无向图:企业专利关联边实现方案求助
问题描述
给定如下结构的DataFrame(实际包含170000条观测数据):
Firm pat cited_pat F_1 [p0,p1,p2] [p0,p1,p2] F_2 [] [] F_3 [p3,p6,p2] [p5,p0,p23,p29,p12,p8] F_4 [p0,p9,p25] [p0,p29,p31] ...
需求:
- 生成所有可能的企业对
F_i、F_j(i < j,避免重复对); - 若两个企业的
pat存在至少一个共同专利,则构建权重为1的边,无需后续判断; - 若
pat无共同专利,则检查cited_pat的共同专利占比(共同数量 / 两个企业cited_pat的总唯一数量),若超过50%则构建权重为1的边。
解决方案
直接生成全量企业对会导致计算量爆炸(17万条数据对应约1.4e11个对),必须用倒排索引+批量匹配的方式优化,以下是高效实现方案:
核心思路
- 先处理
pat匹配:为每个专利建立对应企业的倒排索引,批量生成共享专利的企业对,标记为权重1的边; - 再处理剩余对的
cited_pat匹配:对未通过pat匹配的企业对,计算其引用专利的共同占比,筛选符合条件的对并标记权重1; - 合并结果:合并两类边并去重,得到最终的边列表。
代码实现
import pandas as pd from itertools import combinations from collections import defaultdict # 替换为你的实际DataFrame(示例为读取CSV,可根据数据源调整) df = pd.read_csv("your_firm_data.csv") # ---------------------- 步骤1:处理pat的共同匹配 ---------------------- # 构建专利到企业的倒排索引 pat_to_firms = defaultdict(set) for _, row in df.iterrows(): firm = row['Firm'] for p in row['pat']: pat_to_firms[p].add(firm) # 生成所有共享pat的企业对(自动去重) pat_edges = set() for firms in pat_to_firms.values(): if len(firms) >= 2: for pair in combinations(sorted(firms), 2): pat_edges.add(pair) # 转换为标准边表格式 pat_edges_df = pd.DataFrame(pat_edges, columns=['Firm_i', 'Firm_j']) pat_edges_df['weight'] = 1 # ---------------------- 步骤2:处理cited_pat的匹配(仅针对未通过pat匹配的企业对) ---------------------- # 预存每个企业的pat和cited_pat集合,避免重复查询DataFrame firm_pat_map = {row['Firm']: set(row['pat']) for _, row in df.iterrows()} firm_cited_map = {row['Firm']: set(row['cited_pat']) for _, row in df.iterrows()} # 获取所有可能的企业对,排除已通过pat匹配的对 all_firms = sorted(df['Firm']) all_pairs = set(combinations(all_firms, 2)) remaining_pairs = all_pairs - pat_edges # 筛选符合cited_pat占比要求的对 cited_edges = [] for firm_i, firm_j in remaining_pairs: cited_i = firm_cited_map[firm_i] cited_j = firm_cited_map[firm_j] # 跳过双方无引用专利的无效情况 if not cited_i and not cited_j: continue common_count = len(cited_i & cited_j) total_unique = len(cited_i | cited_j) if total_unique > 0 and common_count / total_unique > 0.5: cited_edges.append((firm_i, firm_j, 1)) # 转换为标准边表格式 cited_edges_df = pd.DataFrame(cited_edges, columns=['Firm_i', 'Firm_j', 'weight']) # ---------------------- 步骤3:合并所有边并输出 ---------------------- final_edges = pd.concat([pat_edges_df, cited_edges_df], ignore_index=True) # 保存结果到CSV(可选) final_edges.to_csv("firm_edges_result.csv", index=False)
针对17万条数据的优化建议
- 预存集合:代码中已预存每个企业的专利集合,避免重复从DataFrame查询,大幅提升迭代效率;
- 减少无效计算:仅对未通过
pat匹配的企业对计算cited_pat占比,直接砍掉大部分计算量; - 内存优化:若内存不足,可分批次处理企业对,或用Dask等分布式框架拆分计算;
- 倒排索引二次优化:对
cited_pat也可先通过倒排索引筛选出共享至少一个引用专利的企业对,再计算占比,进一步缩小计算范围。
内容的提问来源于stack exchange,提问作者Lusian
相关产品推荐
相关产品推荐

