使用 Stata 筛选绿色低碳技术相关专利

视频讲解中有个地方讲解错了,更新后的讲义材料里面已经注明了,以更新后的讲义材料为准。

前不久给大家分享过一些绿色低碳技术相关的专利数据。由于绿色低碳专利的分类标准中有全部涉及和部分涉及两种,所以筛选起来很困难,今天的课程中我们将会讲解如何进行这种筛选。

pdf 转 xlsx

筛选绿色低碳专利使用的标准是国家知识产权局印发的《绿色低碳技术专利分类标准》,附件中有 pdf 文件。

在之前的课程:使用 Stata 提取和处理数字经济核心产业分类与国际专利分类参照关系表 中我们讲解过类似的 pdf 文件转 xlsx 并整理得到规整的 dta 文件的操作。这里就不再赘述了,附件中的 绿色低碳技术专利IPC对照表.dta 就是整理结果:

use 绿色低碳技术专利IPC对照表.dta, clear

全部涉及的很容易处理,和之前课程中讲解的类似。部分涉及则是指该分类号下只有部分满足条件的专利才是绿色低碳专利。

检索式翻译成正则表达式

《绿色低碳技术专利分类标准》文件的后面也提供了检索关键词,也就是在某些分类号下的专利,只有标题和摘要中含特定关键词才能算是绿色低碳专利。

例如其中有一条:

参考关键词:(煤 OR COAL) (2N) (采 OR 矿 OR 井 OR EXCAVAT* OR MINE OR MINING OR PRODUCTING) 参考检索式:IPC=(E02D17/20 OR E02D19/06) AND TIABC=((煤 OR COAL) (2N) (采 OR 矿 OR 井 OR EXCAVAT* OR MINE OR MINING OR PRODUCTING))

Stata 中当然是不支持这种参考检索式的,所以我们需要把这些检索式一一翻译成正则表达式。这里有一些注意事项:

  1. IPC 表示 IPC 专利分类号;
  2. TIABC 表示标题+摘要;
  3. 检索式中的 N、W 和 S 是检索词的连接关系符号。N 没有顺序的限制,W 有顺序限制,S则是在同一句。1/2/3的数字表示两个检索词之间的隔的字数(小于等于该数字)。如检索“车座”(1N)“车把”,可以检索出“车座和车把”、“车把和车座”、“车座车把”、“车把车座”等将车座与车把间隔小于等于1个字并且没有顺序的语句,但检索“车座”(1W)“车把”仅能检索出“车座和车把”或“车座在车把”、“车座车把”等将车座与车把间隔小于等于1个字并且有顺序的语句。

因此例如这个翻译成 Stata 支持的正则表达式应该是:

:=> (煤 OR COAL) (2N) (采 OR  矿 OR  井 OR EXCAVAT* OR MINE OR MINING OR
PRODUCTING)
:=> ustrregexm(text, "((煤)|(COAL))(.{0,2})((采)|(矿)|(井)|(EXCAVAT)|(MINE)|(MINING)|(PRODUCTING))")|ustrregexm(text, "((采)|(矿)|(井)|(EXCAVAT)|(MINE)|(MINING)|(PRODUCTING))(.{0,2})((煤)|(COAL))")

在正则表达式中,() 的一种功能是把被括住的内容视为整体,.{0,2} 表示 <= 两个字符,由于这里使用了 2N,所以需要考虑两种情况。

可以先测试下这个正则表达式是否有效:

clear all
set obs 6
input str100 text
"煤炭开采"
"煤采"
"煤炭开发开采"
"coal-mining"
开采煤炭
"co-mining"
compress
gen code = `"ustrregexm(text, "((煤)|(COAL))(.{0,2})((采)|(矿)|(井)|(EXCAVAT)|(MINE)|(MINING)|(PRODUCTING))")|ustrregexm(text, "((采)|(矿)|(井)|(EXCAVAT)|(MINE)|(MINING)|(PRODUCTING))(.{0,2})((煤)|(COAL))")"'
gen res = `=code[_n]'

format code %10s

list text res in 1/6

*> +--------------------+
*> | text res |
*> |--------------------|
*> 1. | 煤炭开采 1 |
*> 2. | 煤采 1 |
*> 3. | 煤炭开发开采 0 |
*> 4. | COAL-MINING 1 |
*> 5. | 开采煤炭 1 |
*> |--------------------|
*> 6. | CO-MINING 0 |
*> +--------------------+

可以看到煤炭开发开采不符合,因为“煤”和“采”之间有 4 个字,co-minig 不符合,是因为得有完整的 coal 采可以。

附件中的 参考检索式_ocr1.xlsx 是对 参考检索式.pdf 进行文本识别得到的。参考检索式_手动调整.xlsx 文件是我手动一条条翻译的正则表达式。

这些正则表达式里面有三个需要特别注意的:CO、CO2、H2。例如 CO,不能直接写 |CO|,这样是有可能匹配到例如 COOH、CaCO3 之类的,我写的是 |([^a-zA-Z\d](CO)[^a-zA-Z\d])| 也就是 CO 前后不能有其他英文字符和数字,H2 要是直接写的话可能会匹配到 H2O 和 H2O2 之类的。

筛选逻辑

我的想法是按照下面四个步骤筛选:

  1. 首先从总专利里面筛选全部涉及和部分涉及分类下的所有专利。先缩小范围,减少数据的大小;
  2. 筛选全部涉及的部分;
  3. 筛选部分涉及的;
  4. 合并所有筛选的结果。

筛选所有符合分类号筛选条件的专利

附件中我准备了一份 2010 年的专利申请数据:2010年专利申请数据.dta

use 2010年专利申请数据.dta, clear

下面我们根据分类号进行筛选。

首先我们需要删除设计专利、保留关键变量(减少数据大小)以及拆分分类号:

*- 2010 年专利数据
use 2010年专利申请数据, clear
drop if index(专利类型, "设计")
keep newzlid 分类号

*- 排好序
gsort newzlid
*- 统计可拆分的数量:_gipc_count.ado
egen n = ipc_count(分类号), parse(;)

*- 把数据读入 mata 中处理:
mata:
mata clear
// 把分类号数据读入 mata
v1 = st_sdata(., "分类号")

// 转换成行向量
v2 = rowshape(v1, cols(v1))

// 连接起来
v3 = invtokens(v2, ";")

// 使用分号拆分
v4 = ustrsplit(v3, ";")
// 转换成列向量
v5 = colshape(v4, rows(v4))
end

*- 回到 Stata 中
expand n

*- newzlid 的顺序不能变
gsort newzlid

*- 从 mata 的 v5 再创建变量
mata:
stata("cap drop newvar")
st_addvar("strL", "newvar")
st_sstore(., "newvar", v5)
end

drop 分类号 n
ren newvar IPC

replace IPC = ustrregexs(1) if ustrregexm(IPC, "(.*)\(")
save "IPC分类号拆分结果", replace

另外一方面处理 绿色低碳技术专利IPC对照表.dta 数据:

*- 拆分 IPC 对照表
use 绿色低碳技术专利IPC对照表, clear
gather *涉及
drop if missing(value)
split value, parse(, ;)
drop value

ren var 全部或部分涉及
gather value*
drop if missing(value)
replace value = ustrregexs(1) if ustrregexm(value, "(.*)\(")
replace value = ustrregexs(1) if ustrregexm(value, "(.*)\)")
drop var
ren value IPC
gen len = strlen(IPC)
gsort 绿色低碳技术ID IPC
gen ipcid = _n
tab len
save "data1", replace

*- 1. 长度为 3,范围
use data1, clear
tab len
keep if len == 3
order 绿色低碳技术ID ipcid
drop len
save ipcres1, replace

*- 2. 长度为 4,范围
use data1, clear
tab len
keep if len == 4
order 绿色低碳技术ID ipcid
drop len
save ipcres2, replace

*- 3. 长度为 8、9、10,具体
use data1, clear
tab len
keep if inlist(len, 8, 9, 10)
drop len
order 绿色低碳技术ID ipcid
save ipcres3, replace

这样就可以分别根据这三个文件筛选了:

*- ipcres1
use IPC分类号拆分结果, clear
replace IPC = substr(IPC, 1, 3)
recast str3 IPC
joinby IPC using ipcres1
gsort newzlid
duplicates drop _all, force
drop IPC
save 第一部分, replace

*- ipcres2
use IPC分类号拆分结果, clear
replace IPC = substr(IPC, 1, 4)
recast str4 IPC
joinby IPC using ipcres2
gsort newzlid
duplicates drop _all, force
drop IPC
save 第二部分, replace

*- ipcres3
use IPC分类号拆分结果, clear
recast str300 IPC
compress
joinby IPC using ipcres3
gsort newzlid
duplicates drop _all, force
drop IPC
save 第三部分, replace

*- 合并三部分结果
use 第一部分, clear
append using 第二部分
append using 第三部分
compress
foreach i of varlist _all {
cap format `i' %10s
}
save 初步筛选结果, replace

这样我们就初步筛选所有可能涉及的绿色低碳专利了。

从初步筛选结果中提取全部涉及的

全部涉及的就直接保留即可:

use 初步筛选结果, clear
keep if 全部或部分涉及 == "全部涉及"
drop 全部或部分涉及
save "全部涉及筛选结果", replace

从初步筛选结果中提取部分涉及的

再保留部分涉及的结果:

use 初步筛选结果, clear
drop if 全部或部分涉及 == "全部涉及"
drop 全部或部分涉及
keep newzlid
duplicates drop newzlid, force
merge 1:m newzlid using "IPC分类号拆分结果.dta"
keep if _m == 3
drop _m
merge m:1 newzlid using 2010年专利申请数据.dta
keep if _m == 3
drop _m
drop 分类号 主分类号 专利类型 公开公告号
gen text = 专利名称 + " " + 摘要
drop 专利名称 摘要
replace text = strupper(text)
replace text = subinstr(text, "<SUB>", "", .)
ren IPC 分类号
save 待筛选部分涉及, replace

再回到 参考检索式_手动调整.xlsx 结果上,首先把该文件读取并处理下:

import excel using "参考检索式_手动调整.xlsx", clear first
foreach i of varlist _all {
cap format `i' %10s
}
keep 绿色低碳技术分支 IPC分类 参考关键词
ren 参考关键词 筛选表达式
gen 技术分支编号 = ustrregexs(1) if ustrregexm(绿色低碳技术分支, "(.*\d)\s")
carryforward 技术分支编号, replace
drop 绿色低碳技术分支
gen v1 = ustrregexs(0) if ustrregexm(IPC分类, "\n")
replace IPC分类 = subinstr(IPC分类, v1, " ", .)
drop v1
drop if mi(IPC分类) & mi(筛选表达式)
replace IPC分类 = subinstr(IPC分类, " ", "", .)
order 技术分支编号
split IPC分类, parse(,)
drop IPC分类
gen id = _n
gather IPC分类*
gsort id
replace 筛选表达式 = "" if 筛选表达式 == "无"
drop var
drop if mi(value)
order id
replace 技术分支编号 = subinstr(技术分支编号, " ", "", .)
ren value 分类号
replace 筛选表达式 = "1 == 1" if mi(筛选表达式)
merge m:1 技术分支编号 using 绿色低碳技术专利IPC对照表
keep if _m == 3
keep 筛选表达式 技术分支编号 分类号 绿色低碳技术ID
gen len = strlen(分类号)
save data2, replace

根据 len 拆分:

use data2, clear
keep if len == 3
drop len
ren 分类号 IPC
save bfres3, replace

use data2, clear
keep if len == 4
drop len
ren 分类号 IPC
save bfres4, replace

use data2, clear
keep if len == 5
drop len
ren 分类号 IPC
save bfres5, replace

use data2, clear
keep if len == 6
drop len
ren 分类号 IPC
save bfres6, replace

use data2, clear
keep if inlist(len, 8, 9, 10)
drop len
ren 分类号 IPC
save bfres7, replace

然后就可以分别把这些 bfres* 文件匹配到 待筛选部分涉及.dta 上了:

use 待筛选部分涉及, clear
gen IPC = substr(分类号, 1, 3)
recast str300 IPC
joinby IPC using bfres3
duplicates drop _all, force
keep if `=筛选表达式[_n]'
keep newzlid 绿色低碳技术ID
save 部分涉及第1部分, replace

use 待筛选部分涉及, clear
gen IPC = substr(分类号, 1, 4)
recast str300 IPC
joinby IPC using bfres4
duplicates drop _all, force
keep if `=筛选表达式[_n]'
keep newzlid 绿色低碳技术ID
save 部分涉及第2部分, replace

use 待筛选部分涉及, clear
gen IPC = substr(分类号, 1, 5)
recast str300 IPC
joinby IPC using bfres5
duplicates drop _all, force
keep if `=筛选表达式[_n]'
keep newzlid 绿色低碳技术ID
save 部分涉及第3部分, replace

use 待筛选部分涉及, clear
gen IPC = substr(分类号, 1, 6)
recast str300 IPC
joinby IPC using bfres6
duplicates drop _all, force
keep if `=筛选表达式[_n]'
keep newzlid 绿色低碳技术ID
save 部分涉及第4部分, replace

use 待筛选部分涉及, clear
gen IPC = 分类号
recast str300 IPC
joinby IPC using bfres7
duplicates drop _all, force
keep if `=筛选表达式[_n]'
keep newzlid 绿色低碳技术ID
save 部分涉及第5部分, replace

*- 合并结果
use 部分涉及第1部分, clear
forval i = 2/5 {
append using 部分涉及第`i'部分
}
duplicates drop _all, force
save "部分涉及筛选结果", replace

合并全部涉及和部分涉及的结果就是所有的绿色低碳专利了。

use 全部涉及筛选结果, clear
append using 部分涉及筛选结果
keep newzlid 绿色低碳技术ID
duplicates drop _all, force
merge m:1 绿色低碳技术ID using 绿色低碳技术专利IPC对照表
drop if _m == 2
drop _m
drop *涉及
merge m:1 newzlid using 2010年专利申请数据
keep if _m == 3
drop _m
save "2010年绿色低碳专利", replace

在计算专利申请数量时需要注意,专利数据里面有很多申请和授权同时存在的专利,在统计专利数量的时候应该先去除这种重复情况。

统计的时候可以先去除公开公告号里面的 A、B、U、S。其中 A 代表发明专利的申请公开,B 代表发明专利的授权公告,U 代表实用新型专利的授权公告,S 代表外观设计专利的授权公告。

use 2010年绿色低碳专利, clear
*- 去除重复的专利
replace 公开公告号 = subinstr(公开公告号, "A", "", .)
replace 公开公告号 = subinstr(公开公告号, "B", "", .)
replace 公开公告号 = subinstr(公开公告号, "U", "", .)
replace 公开公告号 = subinstr(公开公告号, "S", "", .)
replace 专利类型 = "发明" if index(专利类型, "发明")
*- 使用 duplicates drop 去除重复的
duplicates drop 公开公告号, force
save 2010年绿色低碳专利(去重), replace

也可以统计不同类别的数量:

use 绿色低碳技术专利IPC对照表, clear
keep if !index(技术分支编号, ".")
keep 技术*
save 技术分支类别, replace

use 2010年绿色低碳专利(去重), clear
replace 技术分支编号 = substr(技术分支编号, 1, 1)
drop 技术分支名称
merge m:1 技术分支编号 using 技术分支类别
contract 技术分支名称
gr pie _freq, over(技术分支名称) ///
plabel(_all percent, format(%6.2f)) ///
ti("2010 年绿色低碳专利各类别申请占比") ///
subti("数据处理:微信公众号 RStata") ///
caption("数据来源:国家知识产权局")

点击这里跳转到 RStata 短书平台获取附件:使用 Stata 筛选绿色低碳技术相关专利

评论