「Incremental vs. Breakthrough Innovation: The Role of Technology Spillovers」一文中提出了几个关于衡量渐进性创新与突破性创新的指标:
重复引用次数(Repeatcitations):企业重复引用过去 5 年内专利的引用次数占总引用次数的比例;
自引次数(Self-citations):企业自引占总引用次数的比例;
已知领域(known areas):企业熟悉的技术分类下的专利数量占企业专利申请总数的比例;
技术相似性(Tech Proximity):企业在 t 年的专利技术领域与 t-1 年专利技术领域之间的相似性。该值越小意味着更多的突破性创新。具体的指标为:
被引次数(Citations):采用 Citations90、Citations99 分别衡量被引次数在前 10% 和 1% 的专利数量除以企业当年专利申请总数。
其中前三个指标反映的是企业的渐进性创新,后两个指标反映的是企业的突破性创新。
今天我们先讲解专利相似性的计算,这个涉及到了公式,稍微比其他几个复杂点。
之前也给大家讲解过类似的课程:
使用 Stata 计算专利技术空间相似度、企业层面的知识宽度、新技术空间专利申请及IPC号新增数:https://rstata.duanshu.com/#/brief/course/535f9284c31d47c2861b8cd1384394d0
使用 Stata 计算企业技术相似度:交叉数据集、矩阵运算和 Mata 方法:https://rstata.duanshu.com/#/brief/course/11ec07a861384c218f5f77582875b0a2
第一个课程里面其实讲解过跨年的技术相似度,第二个计算的其实是企业间的技术相似度。虽然第一个课程中讲解过类似的内容,不过方法感觉还不是很好用,今天再给大家介绍一种更好用的方法。
读取专利数据并去除重复的 本次课程我们将以上市公司专利数据为例进行讲解。上市公司专利数据来自这里:
1985~2024 年上市公司与专利数据匹配结果(版本3, 含申请、授权信息):https://rstata.duanshu.com/#/brief/course/04100321f88b411f90429be934934bff
由于数据非常巨大,就没在附件中提供。使用专利数据的时候要特别注意专利数据里面有很多申请和授权同时存在的专利,在统计专利数量的时候应该先去除这种重复情况:
使用前可以先去除公开公告号里面的 A、B、U、S。其中 A 代表发明专利的申请公开,B 代表发明专利的授权公告,U 代表实用新型专利的授权公告,S 代表外观设计专利的授权公告:
cd ~/Desktop/渐进性创新与突破性创新:使用 Stata 计算上市公司跨年专利技术相似度use 1985~2024年上市公司与专利数据匹配结果.dta, clear replace 公开公告号 = subinstr (公开公告号, "A" , "" , .)replace 公开公告号 = subinstr (公开公告号, "B" , "" , .)replace 公开公告号 = subinstr (公开公告号, "U" , "" , .)replace 公开公告号 = subinstr (公开公告号, "S" , "" , .)replace 专利类型 = "发明" if index (专利类型, "发明" )duplicates drop 股票代码 公开公告号, forcekeep 股票代码 年份 newipzlid IPC主分类save rawdata, replace
rawdata.dta 在附件中提供了:
use rawdata, clear list in 1/10
参考文献中使用的技术分类信息来自美国国家经济研究局(NBER)的专利数据库。该数据库提供了从1980年到2006年由美国专利商标局(USPTO)授予的超过300万项专利的详细信息。不过根据前述两个课程的介绍,进来年份的参考文献通常使用 IPC 主分类号的第一位(部)、前三位(大类)、前四位(小类)三种方法作为类别的划分标准。
下面我们依次使用这三种方式进行计算。
方法一:使用部作为技术分类 提取部:
use rawdata, clear drop if mi (IPC主分类)gen class = substr (IPC主分类, 1, 1)drop IPC主分类
每年每家企业的总专利申请量:
destring newipzlid, replace bysort 股票代码 年份: egen totalcount = count (newipzlid)
分类别的数量:
bysort 股票代码 年份 class : egen subcount = count (newipzlid)
计算比率:
gen ratio = subcount / totalcountdrop *count newipzlidduplicates drop _all, forcespread class ratio foreach i of varlist A-H {
排个序:
如果企业只有一年的数据,无法跨年计算,因此删除:
bysort 股票代码: egen count = count (年份)drop if count == 1drop count
现在的数据是这样的:
list in 1/10 *> +-----------------------------------------------------------------------------+ *> | 股票代码 年份 A B C D E F G H | *> |-----------------------------------------------------------------------------| *> 1. | 000001 2003 0 0 0 0 0 0 1 0 | *> 2. | 000001 2010 0 0 0 0 0 0 1 0 | *> 3. | 000001 2013 0 0 0 0 0 0 .5 .5 | *> 4. | 000001 2016 0 0 0 0 0 0 1 0 | *> 5. | 000001 2017 0 0 0 0 0 0 .8333333 .1666667 | *> |-----------------------------------------------------------------------------| *> 6. | 000001 2018 0 0 0 0 0 0 1 0 | *> 7. | 000001 2019 0 0 0 0 0 0 .9300699 .0699301 | *> 8. | 000001 2020 0 0 0 0 0 0 .9007353 .0992647 | *> 9. | 000001 2021 0 .0084746 0 0 0 0 .9350283 .0564972 | *> 10. | 000001 2022 .0012715 .0006357 0 0 0 0 .8900191 .1080737 | *> +-----------------------------------------------------------------------------+
下面我们需要循环企业进行计算,最高效的方式就是使用 Mata 代码了。不过在正式写循环之前,我们先选择平安银行的为例:
* - 以平安银行为例进行计算mata: mat = st_data( 1 :: 11 , 3. .10) resmat = J( rows( mat) , 1 , .) for ( i = 2 ; i <= rows( mat) ; i+ + ) { resmat[ i] = mat[ i, .] * mat[ i- 1 , .] ' / (sqrt((mat[i,.] * mat[i,.]' ) ) * sqrt ( ( mat[ i- 1 , .] * mat[ i- 1 , .] '))) } resmat end
然后就可以循环所有公司的了:
mata: code = st_sdata(., "股票代码") mat = st_data(., 3..10) // 所有互不相同的股票代码 codelist = uniqrows(code) // 年份 year = st_data(., "年份") // 保存到 res1 文件里面 stata("cap erase res1.csv") filename = "res1.csv" fh = fopen(filename, "rw") // 循环公司 for (c = 1; c <= rows(codelist); c++) { codelist[c, 1] // 该公司对应的数据 index = selectindex(code[., 1] :== codelist[c, 1]) tempmat = mat[index, .] tempyear = year[index, .] resmat = J(rows(tempmat), 1, .) for (i = 2; i <= rows(tempmat); i++) { resmat[i] = tempmat[i,.] * tempmat[i-1,.]' / (sqrt((tempmat[i,.] * tempmat[i,.]')) * sqrt((tempmat[i-1,.] * tempmat[i-1,.]'))) } for (i = 1; i <= rows(resmat); i++) { fput(fh, codelist[c, 1] + "," + strofreal(tempyear[i]) + "," + strofreal(resmat[i, .])) } } fclose(fh) end
读取处理结果:
import delimited using res1.csv, clear stringcols(_all) ren (v1 v2 v3) (股票代码 年份 跨年专利技术相似度_IPC1)destring 年份 跨年专利技术相似度_IPC1, replace save data1, replace
方法二:使用大类作为技术分类 大类是 IPC 主分类号的前三个字符。然后代码和上面的类似:
use rawdata, clear drop if mi (IPC主分类)gen class = substr (IPC主分类, 1, 3)drop IPC主分类destring newipzlid, replace bysort 股票代码 年份: egen totalcount = count (newipzlid)bysort 股票代码 年份 class : egen subcount = count (newipzlid)gen ratio = subcount / totalcountdrop *count newipzlidduplicates drop _all, forcespread class ratio foreach i of varlist A01 - H10 { replace `i' = 0 if mi (`i' ) } gsort 股票代码 年份bysort 股票代码: egen count = count (年份)drop if count == 1drop count mata : code = st_sdata(., "股票代码" ) mat = st_data(., 3..127) codelist = uniqrows(code) year = st_data(., "年份" ) stata("cap erase res2.csv" ) filename = "res2.csv" fh = fopen(filename, "rw" ) for (c = 1; c <= rows(codelist); c++) { codelist[c, 1] index = selectindex(code[., 1] :== codelist[c, 1]) tempmat = mat [index, .] tempyear = year[index, .] resmat = J (rows(tempmat), 1, .) for (i = 2; i <= rows(tempmat); i++) { resmat[i] = tempmat[i,.] * tempmat[i-1,.]' / (sqrt ((tempmat[i,.] * tempmat[i,.]')) * sqrt ((tempmat[i-1,.] * tempmat[i-1,.]'))) } for (i = 1; i <= rows(resmat); i++) { fput(fh, codelist[c, 1] + "," + strofreal (tempyear[i]) + "," + strofreal (resmat[i, .])) } } fclose(fh) end import delimited using res2.csv, clear stringcols(_all) ren (v1 v2 v3) (股票代码 年份 跨年专利技术相似度_IPC3)destring 年份 跨年专利技术相似度_IPC3, replace save data2, replace
方法三:使用小类作为技术分类 小类是主分类号的前四位,代码也类似:
use rawdata, clear drop if mi (IPC主分类)gen class = substr (IPC主分类, 1, 4)drop IPC主分类destring newipzlid, replace bysort 股票代码 年份: egen totalcount = count (newipzlid)bysort 股票代码 年份 class : egen subcount = count (newipzlid)gen ratio = subcount / totalcountdrop *count newipzlidduplicates drop _all, forcespread class ratio foreach i of varlist A01B - H10N { replace `i' = 0 if mi (`i' ) } gsort 股票代码 年份bysort 股票代码: egen count = count (年份)drop if count == 1drop count mata : code = st_sdata(., "股票代码" ) mat = st_data(., 3..660) codelist = uniqrows(code) year = st_data(., "年份" ) stata("cap erase res3.csv" ) filename = "res3.csv" fh = fopen(filename, "rw" ) for (c = 1; c <= rows(codelist); c++) { codelist[c, 1] index = selectindex(code[., 1] :== codelist[c, 1]) tempmat = mat [index, .] tempyear = year[index, .] resmat = J (rows(tempmat), 1, .) for (i = 2; i <= rows(tempmat); i++) { resmat[i] = tempmat[i,.] * tempmat[i-1,.]' / (sqrt ((tempmat[i,.] * tempmat[i,.]')) * sqrt ((tempmat[i-1,.] * tempmat[i-1,.]'))) } for (i = 1; i <= rows(resmat); i++) { fput(fh, codelist[c, 1] + "," + strofreal (tempyear[i]) + "," + strofreal (resmat[i, .])) } } fclose(fh) end import delimited using res3.csv, clear stringcols(_all) ren (v1 v2 v3) (股票代码 年份 跨年专利技术相似度_IPC4)destring 年份 跨年专利技术相似度_IPC4, replace save data3, replace
合并三个结果 最后,合并三种结果:
use data1, clear merge 1:1 股票代码 年份 using data2drop _mmerge 1:1 股票代码 年份 using data3drop _mlabel data "数据计算:微信公众号 RStata" save "1985~2024年各上市公司跨年专利技术相似度计算结果" , replace
最后可以绘制一幅图展示下计算结果:
collapse (mean ) 跨年专利技术相似度_IPC1 (mean ) 跨年专利技术相似度_IPC3 (mean ) 跨年专利技术相似度_IPC4, by (年份)tw conn 跨年专利技术相似度_IPC1 跨年专利技术相似度_IPC3 跨年专利技术相似度_IPC4 年份, m (o ...) lp(solid ...) color("254 212 57" "112 154 225" "138 145 151" ) leg(order (1 "跨年专利技术相似度(部)" 2 "跨年专利技术相似度(大类)" 3 "跨年专利技术相似度(小类)" ) pos(6) row(1)) xti("" ) xla(1985(5)2020 2024) yla(0(0.2)1, format (%6.1f)) ti("1986~2024年各年上市公司与上年的平均技术相似度" ) subti("数据处理:微信公众号 RStata" ) caption("数据来源:RStata 数据中心:1986~2024年各年上市公司与上年的平均技术相似度. 2025." "https://tidyfriday.cn/rsdb2/" ) gr export "1986~2024年各年上市公司与上年的平均技术相似度.png" , replace width(4800)
点击这里跳转到 RStata 短书平台获取附件:名师讲堂|渐进性创新与突破性创新:使用 Stata 计算上市公司跨年专利技术相似度
评论