今天给大家分享使用 Python 测算区域技术专业化的方法。该方法参考自林原(2018)《技术流动对区域技术专业化的影响研究》,通过IPC专利分类和RTA指数来综合测度区域的技术专业化程度。
附件中提供了该参考文献的 PDF 文件,感兴趣的小伙伴可以阅读原文。
指标来源与计算原理
区域技术专业化(Regional Technological Specialization)
区域技术专业化是衡量地区在特定技术领域集聚程度的重要指标。该方法的核心思想是:
- IPC专利分类:利用世界知识产权组织(WIPO)的IPC与技术领域对照表,将专利按IPC代码归类到35个技术领域
- RTA指数(Revealed Technological Advantage):计算区域在特定技术领域的相对优势
- CV(变异系数):用调整后RTA的变异系数衡量区域技术专业化的整体程度
RTA指数

调整后RTA

CV计算

计算步骤概述
整个计算过程分为以下几个步骤:
- 数据准备:读取专利数据和WIPO对照表
- 数据清洗:按地区去重(公告号、申请号、专利ID)
- IPC匹配:将专利IPC代码匹配到35个技术领域
- RTA计算:计算各省份各技术领域的RTA和调整后RTA
- CV计算:计算各省份的CV值
- 结果保存:输出CSV文件
使用 reticulate 创建与管理 Python 虚拟环境
在 R 中通过 reticulate 包来调用 Python,最好的实践是为项目创建一个专属的 Python 虚拟环境,将所需依赖隔离到独立空间,避免与系统 Python(如 Anaconda)发生版本冲突。
重要说明(避免”已初始化”报错):reticulate 在 R 会话中只能绑定一次 Python——一旦某个 {python} 代码块运行,Python 解释器就被锁定,之后再调用 use_virtualenv() 会报错:
ERROR: The requested version of Python cannot be used, as another version has already been initialized.
因此,虚拟环境的激活必须在所有 {python} 代码块之前完成。本文档的解决方案是在 setup chunk 中通过 Sys.setenv(RETICULATE_PYTHON = ...) 提前锁定 Python 路径,这是 reticulate 选取 Python 的最高优先级入口。
安装 reticulate(仅首次)
# 设置 CRAN 镜像(knit 时 R 处于非交互模式,不会自动选择镜像) options(repos = c(CRAN = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/"))
# 仅在尚未安装时才安装,避免每次 knit 都重装 if (!requireNamespace("reticulate", quietly = TRUE)) { install.packages("reticulate") message("reticulate 安装完成!") } else { message("reticulate 已安装,版本:", packageVersion("reticulate")) }
|
虚拟环境初始化原理(已在 setup chunk 中完成)
本文档的 setup chunk(隐藏运行)包含如下逻辑:
library(reticulate)
.venv_name <- ".venv" .venv_python <- virtualenv_python(.venv_name)
if (!file.exists(.venv_python)) { virtualenv_create(.venv_name) .venv_python <- virtualenv_python(.venv_name) }
Sys.setenv(RETICULATE_PYTHON = .venv_python) use_virtualenv(.venv_name, required = TRUE)
|
在虚拟环境中安装 Python 包(仅首次)
本项目主要使用 pandas 和 numpy,都是 Python 标准库,不需要额外安装:
py_pkgs <- c("pandas", "numpy") installed <- py_list_packages(".venv")$package need_install <- setdiff(py_pkgs, installed)
if (length(need_install) > 0) { virtualenv_install(".venv", packages = need_install) message("已安装缺失的包:", paste(need_install, collapse = ", ")) } else { message("所有 Python 包已就绪,无需安装") }
|
验证激活状态
# 验证当前绑定的 Python 路径(应指向 .venv 目录) py_config()
|
详细计算代码
数据读取
读取专利数据和WIPO对照表:
import pandas as pd import numpy as np import re from pathlib import Path
DATA_DIR = Path(__file__).parent if '__file__' in dir() else Path(".") PATENT_FILE = DATA_DIR / "2010.csv" WIPO_FILE = DATA_DIR / "WIPO_IPC_and_Technology_Concordance_Table.csv"
df_raw = pd.read_csv(PATENT_FILE, encoding="utf-8") print(f"原始数据行数: {len(df_raw)}")
wipo = pd.read_csv(WIPO_FILE, encoding="utf-8") print(f"WIPO对照表: {len(wipo)} 个技术领域")
|
数据说明:
- 2010.csv:包含各省份各专利的详细信息,包括IPC代码、省市县等字段
- WIPO_IPC_and_Technology_Concordance_Table.csv:WIPO发布的IPC与技术领域对照表,包含35个技术领域
数据预处理——按地区去重
由于同一专利可能在多个地区出现(如共同申请),需要进行去重处理:
# 清理公开公告号(去除末尾字母) df_raw["公开公告号_clean"] = df_raw["公开公告号"].str.replace(r"[A-Z]$", "", regex=True)
# 按地区+公告号去重 df_raw = df_raw.drop_duplicates( subset=["省", "市", "县", "公开公告号_clean"], keep="first" ) print(f"按地区+公告号去重后: {len(df_raw)} 行")
# 按地区+申请号去重 df_raw = df_raw.drop_duplicates( subset=["省", "市", "县", "申请号"], keep="first" ) print(f"按地区+申请号去重后: {len(df_raw)} 行")
# 按地区+专利ID去重 df_raw = df_raw.drop_duplicates( subset=["省", "市", "县", "newipzlid"], keep="first" ) print(f"按地区+专利ID去重后: {len(df_raw)} 行")
|
构建IPC查找表
WIPO对照表中IPC代码的表示规则:
| 规则 |
示例 |
说明 |
| 逗号分隔 |
G09F, G09G, G11B |
多个独立的IPC代码 |
# 号 |
G06# |
该大类下的所有小类 |
## 号 |
H04N-013, H04N-017 |
精确到特定子组 |
-xxx |
H04N-003 |
精确匹配特定代码 |
not 排除 |
(G06# not G06Q) |
排除特定模式 |
此处代码需下载讲义材料查看~
关键函数说明:
- pattern_to_prefix():将各种IPC表示规则转换为统一的前缀格式
- build_ipc_lookup():构建完整的IPC到技术领域的映射,处理逗号分隔、#、排除规则等
IPC匹配函数
# 此处代码需下载讲义材料查看~
# 测试IPC匹配 print("\n测试IPC匹配:") test_ipcs = ["G06F19/00", "G06Q99/00", "H04L", "C12P1/00", "F42B10/26", "G01N", "B01D01/00", "H04N001/01"] for tc in test_ipcs: result = match_ipc_fast(tc, lookup_sorted, exclude_map) tech_names = wipo[wipo["序号"].astype(str).isin(result)]["技术领域名称"].tolist() if result else ["无匹配"] print(f" {tc} -> {', '.join(result)} ({', '.join(tech_names)})")
|
对唯一IPC建立查找表(高效匹配)
为避免对86万条专利逐条匹配,先对唯一IPC代码建立查找表:
此处代码需下载讲义材料查看~
应用查找表到全部数据
print("\n=== Step 6: 应用查找表到全部专利 ===")
df_raw["技术领域"] = df_raw["IPC"].map(ipc_to_tech) df_raw["技术领域"] = df_raw["技术领域"].replace("", np.nan) df_raw["tech_count"] = df_raw["技术领域"].notna().astype(int)
matched_patents = df_raw["tech_count"].sum() unmatched_patents = (df_raw["tech_count"] == 0).sum() print(f"有技术领域匹配的专利数: {matched_patents}") print(f"无匹配的专利数: {unmatched_patents}") print(f"总专利数: {len(df_raw)}")
# 展开数据(一个专利可能属于多个技术领域) df_expanded = df_raw.dropna(subset=["技术领域"])[["省", "省代码", "newipzlid", "技术领域"]].copy() # 按分号展开 df_expanded = df_expanded.assign( 技术领域=df_expanded["技术领域"].str.split(";") ).explode("技术领域") df_expanded = df_expanded.rename(columns={"技术领域": "技术领域序号"}) # 去重 df_expanded = df_expanded.drop_duplicates( subset=["省", "省代码", "newipzlid", "技术领域序号"] ) df_expanded = df_expanded.dropna(subset=["省"])
print(f"展开后行数: {len(df_expanded)}")
|
展开数据说明:
由于一个专利可能同时属于多个技术领域(如同时涉及计算机技术和半导体),需要将专利-领域关系展开为多行。
按省份和技术领域汇总
print("\n=== Step 7: 按省份和技术领域汇总 ===")
tech_by_region = df_expanded.groupby( ["省", "省代码", "技术领域序号"], dropna=False ).size().reset_index(name="专利数量")
print(f"汇总后行数: {len(tech_by_region)}") print(f"涉及省份数: {tech_by_region['省'].nunique()}")
|
计算RTA指数
此处代码需下载讲义材料查看~
RTA解读:
- RTA > 1:该区域在该技术领域具有相对优势
- RTA = 1:与全国平均水平相当
- RTA < 1:该区域在该技术领域处于相对劣势
计算CV
此处代码需下载讲义材料查看~
CV解读:
CV(变异系数)衡量区域技术分布的均衡程度:
- CV越大:区域技术分布越不均衡,专业化程度越高
- CV越小:区域技术分布越均衡,技术多元化程度越高
保存结果
print("\n=== Step 10: 保存结果 ===")
# 添加技术领域名称 tech_names = wipo[["序号", "技术领域名称", "技术领域名称中文"]].copy() tech_names.columns = ["技术领域序号", "技术领域名称", "技术领域名称中文"] tech_names["技术领域序号"] = tech_names["技术领域序号"].astype(str)
tech_df = tech_by_region.merge(tech_names, on="技术领域序号", how="left") tech_df = tech_df.dropna(subset=["省"]).sort_values(["省", "技术领域序号"])
# 保存CV结果 cv_output = "区域技术专业化CV_python.csv" cv_by_region.to_csv(cv_output, index=False, encoding="utf-8-sig") print(f"已保存: {cv_output}")
# 保存技术领域汇总 tech_output = "技术领域按省份汇总_python.csv" tech_df.to_csv(tech_output, index=False, encoding="utf-8-sig") print(f"已保存: {tech_output}")
print("\n=== 完成 ===")
|
R与Python对比
| 步骤 |
R实现 |
Python实现 |
| 数据读取 |
read_csv() |
pd.read_csv() |
| 数据去重 |
distinct() |
drop_duplicates() |
| 字符串替换 |
str_remove() |
str.replace() / re.sub() |
| 分组汇总 |
group_by() %>% summarize() |
groupby().agg() |
| 展开多值 |
separate_rows() |
str.split().explode() |
| 变异系数 |
sd()/mean() |
std()/mean() |
直接运行Python脚本
除了通过Rmd文档运行外,也可以直接运行Python脚本:
# 进入项目目录 cd "/Users/ac/Desktop/使用 Python 测算区域技术专业化"
# 直接运行(需要先安装依赖) python main.py
|
Python脚本会使用内置的 pandas 和 numpy 库,无需额外安装。
点击这里跳转到 RStata 短书平台获取附件:名师讲堂|使用 Python 测算区域技术专业化
评论