在之前的课程中我们讲解过如何使用 Stata 编程计算专利知识宽度:
- 使用 Stata 编程计算企业专利知识宽度:https://rstata.duanshu.com/#/brief/course/7a0978798b6244779e13401ee68f3761
- 使用 Stata 计算专利技术空间相似度、企业层面的知识宽度、新技术空间专利申请及IPC号新增数:https://rstata.duanshu.com/#/brief/course/535f9284c31d47c2861b8cd1384394d0
今天我们再介绍一下如何使用 Mata 加快计算速度,以及编写用于计算专利知识宽度的 egen 函数。
本次课程将会讲解下面三篇文献中提供的专利知识宽度计算方法:
- 创新追赶战略抑制了中国专利质量么_张杰.pdf
- 网络基础设施建设、信息可得性与企业创新边界_沈坤荣.pdf
- 专利质量对企业出口竞争力的影响机制_基于知识宽度视角的探究_李宏.pdf
附件中也提供了文献的 pdf 文件。
分类号方法(大组):张杰、郑文平(2020,经济研究)
第一种是张杰、郑文平(2020,经济研究)中介绍的方法:

经过上面的计算可以得到专利层面的知识宽度信息,然后可以汇总到企业层面,具体来说又分为两种,均值法和中位数方法。
在之前的课程中我们介绍过使用 ado 编程的方法:
use data, clear ren 分类号 IPC
drop if !index(IPC, "/")
split IPC, parse(";") ren IPC 分类号
gather IPC* drop if value == "" save temp.dta, replace
use temp.dta, clear foreach i of varlist _all { cap format `i' %10s } gen 大组 = ustrregexs(1) if ustrregexm(value, "(.*)/(.*)")
bysort newzlid: egen z1 = count(newzlid) bysort newzlid 大组: egen z2 = count(newzlid) bysort newzlid 大组: keep if _n == _N gen double z3 = z2 / z1
bysort newzlid: egen z4 = sum(z3^2) gen patent_knowledge = 1 - z4 drop z* bysort newzlid: keep if _n == _N gsort newzlid drop 大组 var value ren 分类号 IPC ren patent_knowledge 旧方法计算的专利知识宽度
|
这里使用了 split 和 gather,对于观测值较多的数据,这种方法是非常耗时的。下面使用 mata 方法计算:
*- 使用 Mata 提升速度 mata: // uniquerow() 函数的功能是对列向量进行排序去重 string vector uniquerow(string vector x) { b = uniqrows(rowshape(x, cols(x))) return(colshape(b, rows(b))) }
// 读取 IPC 变量 v = st_sdata(., "IPC")
// ipccountres 用于存储计算结果 ipccountres = J(rows(v), 1, .)
// 循环所有的分类号 for(z=1;z<=rows(v);z++){
// 分类号之间使用 ; 分开 a = ustrsplit(v[z], ";") aa = J(1, cols(a), "") for(t=1;t<=cols(a);t++){ // 提取每个分类号的大组 b = ustrsplit(a[t], "/") aa[t] = b[1] }
// bb 是所有互不相同的大组 bb = uniquerow(aa)
// cc 是用来存储每个大组的数量 cc = J(1, cols(bb), 0)
// 循环统计每个大组的数量 for(i=1;i<=cols(bb);i++) { for(j=1;j<=cols(aa);j++) { if(aa[j]==bb[i]) { cc[i] = cc[i] + 1 } } }
// 计算专利知识宽度 ipccountres[z] = 1 - sum((cc/sum(cc)):^2) }
// 根据 ipccountres 创建新变量 stata("cap drop newufvar") st_addvar("double", "newufvar") st_store(., "newufvar", ipccountres) end
*- 重命名 ren newufvar Mata方法计算的专利知识宽度
|
为了方便使用,我把这些代码封装成了一个 egen 函数:_gipc_pk.ado
egen egen函数计算的专利知识宽度 = ipc_pk(IPC), parse(;)
|
这样原来需要几十行代码,数十分钟才能运行完的程序,现在只需要一行代码、数秒钟即可。
分类号方法(大类):沈坤荣(2023,工业经济)
沈坤荣(2023,工业经济)中计算专利知识宽度的方法和上面介绍的略有不同:

所以我们可以先提取分类号的前 3 位(也就是大类,而上面是使用大组信息):
egen ipc1_3 = ipc_sub(IPC), parse(;) from(1) to(3)
|
使用 ipc_sub() 函数需要把 _gipc_sub.ado 文件放在工作目录下,关于该函数的编写和使用,可以学习之前的课程:使用 Stata 处理专利数据的分类号:https://rstata.duanshu.com/#/brief/course/1cfb2e8e8e5f4716959fc78bbaf6d446
然后就可以使用 ipc_pk() 计算专利知识宽度了:

egen pk1_3 = ipc_pk(ipc1_3), parse(;)
|
主分类号方法:李宏、王云廷等(2021,世界经济研究)
李宏、王云廷等(2021,世界经济研究)给出了另外一种计算专利知识宽度的方法:

这样直接就可以得到企业-年份层面的专利质量数据了。
特别需要注意的是,这里计算 t 年的知识宽度是使用 截止 t 年的所有专利。
首先简单把数据整理下:
clear all use data2, clear ren 分类号 IPC
replace 公开公告号 = subinstr(公开公告号, "A", "", .) replace 公开公告号 = subinstr(公开公告号, "B", "", .) replace 公开公告号 = subinstr(公开公告号, "U", "", .) replace 公开公告号 = subinstr(公开公告号, "S", "", .)
duplicates drop 股票代码 公开公告号, force
drop if !index(IPC, "/")
egen IPC_main = ipc_sub0(IPC), parse(;) choose(1)
replace IPC_main = ustrregexs(1) if ustrregexm(IPC_main, "(.*)\(") compress drop 公开公告号 save data2a, replace
|
由于这里并不需要进行 split 和 gather,所以直接使用 Stata 计算也是很快的:
use data2a, clear gen 大组 = ustrregexs(1) if ustrregexm(IPC_main, "(.*)/(.*)")
bysort 股票代码 年份 大组: egen Zimt = count(newzlid)
bysort 股票代码 年份 大组: keep if _n == _N bysort 股票代码 大组 (年份): replace Zimt = sum(Zimt) save Zimt, replace
use data2a, clear bysort 股票代码 年份: egen Zit = count(newzlid) bysort 股票代码 年份: keep if _n == _N
bysort 股票代码 (年份): replace Zit = sum(Zit) save Zit, replace
use Zimt, clear keep 股票代码 年份 Zimt merge m:1 年份 股票代码 using Zit drop _m gen z1 = Zimt / Zit gen z2 = z1 ^ 2 bysort 股票代码 年份: egen z3 = sum(z2) gen patent_knowledge = 1 - z3 drop Z* z* bysort 股票代码 年份: keep if _n == _N keep 股票代码 年份 patent_knowledge ren patent_knowledge 公司专利知识宽度 save "公司专利知识宽度", replace
list in 1/10
|
关于这种方法的实现,我也尝试使用 Mata 编写了一些程序,不过速度也都很慢,还不如上面的代码。主要是字符串循环累加很费时间。所以还要使用 Mata 了。
点击这里跳转到 RStata 短书平台获取附件:名师讲堂|使用 Stata 计算专利知识宽度:Mata 方法
评论