欢迎各位名师讲堂会员参加明晚 8 点的直播课:「使用 Stata 筛选绿色技术专利(国家知识产权局标准)」
前不久给大家分享过一些绿色技术相关的专利数据。由于绿色专利的分类标准中有全部涉及和部分涉及两种,所以筛选起来很困难,今天的课程中我们将会讲解如何进行这种筛选。
1985~2024 年绿色专利申请与授权数据(国家知识产权局标准):https://rstata.duanshu.com/#/brief/course/9cfa513db3a54891bef466caac9e6a62
pdf 转 xlsx
筛选绿色专利使用的标准是国家知识产权局印发的《绿色技术专利分类体系》,附件中有 pdf 文件。
从该 pdf 文件中可以提取绿色专利技术专利分类体系表:绿色技术专利分类体系-table.pdf
,这可以借助浏览器的打印功能得到。使用 Adobe Acrobat 软件可以把 pdf 文件转换成 xlsx 文件,附件中的 绿色技术专利分类体系-table.xlsx
就是转换结果。简单手动整理后再使用 Stata 处理下:
import excel using "绿色技术专利分类体系-table.xlsx", clear first
drop D
compress
foreach i of varlist _all {
cap format `i' %10s
}
replace 国际专利分类 = 国际专利分类[_n] + 国际专利分类[_n + 1] if mi(技术分支编号[_n + 1])
drop if mi(技术分支编号)
gen 绿色专利分类ID = _n
order 绿色专利分类ID
gen temp = ustrregexs(0) if ustrregexm(国际专利分类, "\n")
replace 国际专利分类 = subinstr(国际专利分类, temp, "", .)
drop temp
gen temp = ustrregexs(0) if ustrregexm(技术分支名称, "\n")
replace 技术分支名称 = subinstr(技术分支名称, temp, "", .)
drop temp
replace 国际专利分类 = subinstr(国际专利分类, " ", "", .)
replace 国际专利分类 = subinstr(国际专利分类, ";", ",", .)
split 国际专利分类, parse("部分涉及")
foreach i of varlist _all {
cap format `i' %10s
}
replace 国际专利分类1 = subinstr(国际专利分类1, "全部涉及:", "", .)
replace 国际专利分类2 = subinstr(国际专利分类2, ":", "", .)
replace 技术分支编号 = "8.2" if 技术分支编号 == "8.199999999999999"
replace 技术分支编号 = "9.2" if 技术分支编号 == "9.199999999999999"
replace 技术分支编号 = "9.3" if 技术分支编号 == "9.300000000000001"
ren 国际专利分类1 全部涉及
ren 国际专利分类2 部分涉及
compress
foreach i of varlist _all {
cap format `i' %10s
}
drop 国际专利分类
replace 技术分支编号 = subinstr(技术分支编号, " ", "", .)
save 专利分类号筛选标准, replace
使用分类号进行专利筛选非常简单,这个之前就讲解过:
使用 Stata 提取和处理数字经济核心产业分类与国际专利分类参照关系表:https://rstata.duanshu.com/#/course/b2c71978336b4b39b69f05d6537d9d8f
全部涉及的就是指该分类下的所有专利都是绿色专利,部分涉及的则需要结合关键词进行筛选。
从该 pdf 文件中可以提取参考检索式部分:参考检索式.pdf
,参考检索式.xlsx
是转换并手动整理得到的结果,使用 Stata 处理下:
import excel using "参考检索式.xlsx", clear first
*- 替换换行符
gen temp = ustrregexs(0) if ustrregexm(参考关键词, "(\n)")
replace 参考关键词 = subinstr(参考关键词, temp, "", .)
drop temp
gen temp = ustrregexs(0) if ustrregexm(IPC分类, "(\n)")
replace IPC分类 = subinstr(IPC分类, temp, "", .)
drop temp
gen 绿色专利分类ID = _n
order 绿色专利分类ID
replace IPC分类 = subinstr(IPC分类, " ", "", .)
foreach i of varlist _all {
cap format `i' %20s
}
replace 参考关键词 = subinstr(参考关键词, " ", " ", .)
replace 参考关键词 = subinstr(参考关键词, " ", " ", .)
save 参考检索式, replace
检索式翻译成正则表达式
例如其中有一条:
参考关键词:(煤 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 中当然是不支持这种参考检索式的,所以我们需要把这些检索式一一翻译成正则表达式。这里有一些注意事项:
IPC 表示 IPC 专利分类号; TIABC 表示标题+摘要; 检索式中的 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})|((?:\s*\b\w+\b\s*){0,2}))(采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING)|(采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(煤|COAL)")
在正则表达式中,,((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))
表示 <= 两个字符或单词,由于这里使用了 2N
,所以需要考虑两种情况。这里的一些字符含义:
()
的一种功能是把被括住的内容视为整体;|
表示或者;.
用于匹配任意字符;{0,2}
表示 0~2 个;\w+
:匹配一个或多个单词字符。\w
代表任何字母数字字符(包括下划线),+表示前面的字符至少出现一次;\s
用于匹配空格;\b
用于匹配单词边界;(?: ... )
:这是一个非捕获组(non-capturing group),意味着匹配的内容不会被保存以供后续引用。它用于分组但不捕获匹配的内容。因此 (?:\s*\b\w+\b\s*){0,2})
表示的是匹配 0~2 个单词(对于英文),(.{0,2})
表示 0~2 个字符(对于汉字)。
因此 1N~5N 对应的正则表达式如下:
((.{0,1})|((?:\s*\b\w+\b\s*){0,1}))
((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))
((.{0,3})|((?:\s*\b\w+\b\s*){0,3}))
((.{0,4})|((?:\s*\b\w+\b\s*){0,4}))
((.{0,5})|((?:\s*\b\w+\b\s*){0,5}))
可以先测试下这个正则表达式是否有效:
clear all
set obs 6
input str100 text
"煤炭开采"
"煤采"
"煤炭开发开采"
"coal-mining"
开采煤炭
"co-mining"
compress
replace text = strupper(text)
gen code = `"ustrregexm(text, "(煤|COAL)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING)|(采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING)((.{0,2})|((?:\s*\b\w+\b\s*){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 采可以。
另外一个常用的表达可以分别用下面几种方式表达:
SAV*
表示 sav 开头的单词,其中*
可以表达为:\w*\b
;“H2”
表示特指氢气,如果直接使用 H2 可能会匹配到 H2O 之类的,因此应该使用类似这样的表达:([^a-zA-Z\d](H2)[^a-zA-Z\d])
,也就是 H2 的前后都不应该有英文字符或者数字了;(S)
表示前后内容在同一句话中,可以用([^.。!!;;])
表示,也就是两个部分之间不应有表示句子结束的符号。
去除重复的就可以得到所有需要翻译的检索式了:
use 参考检索式, clear
keep 参考关键词
duplicates drop 参考关键词, force
drop if mi(参考关键词)
gsort 参考关键词
save 待翻译正则表达式, replace
export excel using 待翻译正则表达式.xlsx, replace firstrow(variables)
一共 71 个,工作量其实还挺大的。
N 字符的存在让这个工作变得非常难做。为此我编写了一个 R 脚本:
library(tidyverse)
read_csv("待转换.csv", col_names = F) %>%
mutate(X2 = map(X1, function(z){
str <- str_match(z, "^\\((.*)\\)|$")[1,2]
str_split_1(str, pattern = "\\s\\(\\dN\\)\\s") -> res
str_match(str, pattern = "\\s\\(\\dN\\)\\s") -> splitstr
apply(gtools::permutations(length(res), length(res)), 1, function(x){
res[x]
}) %>%
t() %>%
apply(1, function(x){
paste0("(", paste0(x, collapse = splitstr), ")|")
}) %>%
as_tibble()
})) %>%
select(-X1) %>%
unnest(X2) %>%
mutate(value = str_remove_all(value, " ")) %>%
write_csv("待转换.csv", col_names = F, quote = "none")
这段代码可以把 待转换.csv
中的内容转换成需要的样子,例如如下内容:
((HYDROGEN* OR “H2” OR氢) (5N) (FUEL OR 燃料))|
运行上面的代码就会被转换成如下内容:
((HYDROGEN*OR“H2”OR氢)(5N)(FUELOR燃料))|
((FUELOR燃料)(5N)(HYDROGEN*OR“H2”OR氢))|
需要注意格式需要严格按照 ((...)(...N)(...))|
这样的结构。
待翻译正则表达式-翻译结果.xlsx
就是翻译得到的结果,待翻译正则表达式-翻译结果.dta
是读取成 dta 的结果:
import excel using "待翻译正则表达式-翻译结果.xlsx", clear first
save "待翻译正则表达式-翻译结果", replace
再把这个结果和去重前的合并:
use 参考检索式, clear
drop 绿色专利分类ID
replace IPC分类 = IPC分类[_n] + IPC分类[_n + 1] if mi(绿色技术分支[_n + 1]) & mi(参考关键词[_n + 1])
drop if mi(绿色技术分支) & mi(参考关键词)
compress
foreach i of varlist _all {
cap format `i' %10s
}
gen 技术分支编号 = ustrregexs(0) if ustrregexm(绿色技术分支, "[\d.]*")
replace IPC分类 = subinstr(IPC分类, " ", "", .)
gen temp = ustrregexs(0) if ustrregexm(IPC分类, "\n")
replace IPC分类 = subinstr(IPC分类, temp, "", .)
drop temp
drop 绿色技术分支
order 技术分支编号
carryforward 技术分支编号, replace
gen myid = _n
order myid
drop if mi(技术分支编号)
merge m:1 参考关键词 using "待翻译正则表达式-翻译结果"
drop _m
gsort myid
drop 参考关键词
split IPC分类, parse(",")
drop IPC分类
gather IPC分类*
drop if missing(value)
drop var
save tempdata1, replace
不过这里需要注意,有几个含有 NOT 条件的:
use tempdata1, clear
keep if index(value, "NOT")
我们再把这些筛选条件加到正则表达式里面:
use tempdata1, clear
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "C01B3/04")"' if value == "C01B3/00(NOT:C01B3/04)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "F03B13/02", "F03B13/04", "F03B13/12")"' if value == "F03B13/00(NOT:F03B13/02ORF03B13/04ORF03B13/12)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "E02B9/08")"' if value == "E02B9/00(NOT:E02B9/08)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "F03B17/04")"' if value == "F03B17/02(NOT:F03B17/04)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "C10G1/10")"' if value == "C10G1/00(NOT:C10G1/10)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "C10L3/02")"' if value == "C10L3/00(NOT:C10L3/02"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "G01R31/01")"' if value == "G01R31/00(NOTG01R31/01"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "B01D53/84")"' if value == "B01D53/34(NOT:B01D53/84)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "C09K23/50")"' if value == "(C09K23/00NOTC09K23/50)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "B01F17/50")"' if value == "(B01F17/00NOTB01F17/50)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "C08L101/16")"' if value == "(C08L101/00NOTC08L101/16)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "B60K1/04")"' if value == "B60K1/00NOTB60K1/04"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "B60K6/28", "B60K6/30")"' if value == "B60K6/00NOT(B60K6/28ORB60K6/30)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "B60W10/26")"' if value == "B60W10/00NOTB60W10/26"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "B60W20/16")"' if value == "B60W20/00NOTB60W20/16"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "C05G3/02")"' if value == "(C05G3/00NOTC05G3/02)"
replace 正则表达式 = 正则表达式 + "&" + `"!index(分类号, "C05G3/60")"' if value == "(C05G3/00NOTC05G3/60)"
replace value = "C01B3/00" if value == "C01B3/00(NOT:C01B3/04)"
replace value = "F03B13/00" if value == "F03B13/00(NOT:F03B13/02ORF03B13/04ORF03B13/12)"
replace value = "E02B9/00" if value == "E02B9/00(NOT:E02B9/08)"
replace value = "F03B17/02" if value == "F03B17/02(NOT:F03B17/04)"
replace value = "C10G1/00" if value == "C10G1/00(NOT:C10G1/10)"
replace value = "C10L3/00" if value == "C10L3/00(NOT:C10L3/02"
replace value = "G01R31/00" if value == "G01R31/00(NOTG01R31/01"
replace value = "B01D53/34" if value == "B01D53/34(NOT:B01D53/84)"
replace value = "C09K23/00" if value == "(C09K23/00NOTC09K23/50)"
replace value = "B01F17/00" if value == "(B01F17/00NOTB01F17/50)"
replace value = "C08L101/00" if value == "(C08L101/00NOTC08L101/16)"
replace value = "B60K1/00" if value == "B60K1/00NOTB60K1/04"
replace value = "B60K6/00" if value == "B60K6/00NOT(B60K6/28ORB60K6/30)"
replace value = "B60W10/00" if value == "B60W10/00NOTB60W10/26"
replace value = "B60W20/00" if value == "B60W20/00NOTB60W20/16"
replace value = "C05G3/00" if value == "(C05G3/00NOTC05G3/02)"
replace value = "C05G3/00" if value == "(C05G3/00NOTC05G3/60)"
然后还有一个注意事项,我们之前提到过 IPC 分类号中的大组和小组看似是包含关系,实际上是对应关系,这个可以参考这个课程:
使用 R 语言爬取处理 WIPO 绿色专利分类数据:https://rstata.duanshu.com/#/brief/course/6edd7ed2f3284915b2c916ead3fbfd10
但是根据知识产权局的这个回复来看:
筛选标准里面的大组和小组实际上是看作包含关系,例如 C01B3/00(NOT:C01B3/04)
表示的是所有 IPC 分类号开头是 C01B3
的,但是 C01B3/04
除外。
也就是说按照知识产权局的意思,大组的分类包含其下的小组,所以把所有的 /00 去除:
replace value = subinstr(value, "/00", "", .)
ren value IPC
save 参考关键词整理结果, replace
筛选逻辑
我的想法是按照下面四个步骤筛选:
首先从总专利里面筛选全部涉及和部分涉及分类下的所有专利。先缩小范围,减少数据的大小; 筛选全部涉及的部分; 筛选部分涉及的; 合并所有筛选的结果。
筛选所有符合分类号筛选条件的专利
附件中我准备了一份 2010 年的专利申请数据:2010年专利申请数据.dta
use 2010年专利申请数据.dta, clear
下面我们根据分类号进行筛选。
首先我们需要删除设计专利、保留关键变量(减少数据大小)以及拆分分类号。
在之前的课程「使用 Stata 进行绿色专利的筛选」中我介绍过 split + gather 以及 split + 循环 append 的方法:
使用 Stata 进行绿色专利的筛选:https://rstata.duanshu.com/#/brief/course/2fd6838527754c94a3f5ccb0e3ba7be1
在课程「使用 Stata 处理专利数据的分类号」中我也介绍了使用 Mata 的方法:
名师讲堂|使用 Stata 处理专利数据的分类号:https://rstata.duanshu.com/#/brief/course/1cfb2e8e8e5f4716959fc78bbaf6d446
这里我们使用 Mata 方法:
*- 2010 年专利数据
use 2010年专利申请数据, clear
drop if !index(IPC, "/")
keep ipzlid IPC
ren IPC 分类号
*- 排好序
gsort ipzlid
*- 统计可拆分的数量:_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
*- ipzlid 的顺序不能变
gsort ipzlid
*- 从 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
list in 1/10
*> +------------------------+
*> | ipzlid IPC |
*> |------------------------|
*> 1. | 2010000001 A47J37/08 |
*> 2. | 2010000002 A47J37/08 |
*> 3. | 2010000003 A47J37/10 |
*> 4. | 2010000004 A47J37/12 |
*> 5. | 2010000005 A47J37/12 |
*> |------------------------|
*> 6. | 2010000005 A21B5/08 |
*> 7. | 2010000006 A47J37/12 |
*> 8. | 2010000007 A47J43/07 |
*> 9. | 2010000008 A47J47/08 |
*> 10. | 2010000009 A47J47/16 |
*> +------------------------+
然后就可以根据分类号条件进行筛选了。
我们把分类号筛选条件按照长度进行拆分:
use 参考关键词整理结果, clear
gen len = strlen(IPC)
tab len
gsort len
cap mkdir "res1"
forval l = 3/12 {
preserve
keep if len == `l'
save res1/`l', replace
restore
}
循环匹配筛选:
cap mkdir "res2"
use IPC分类号拆分结果.dta, clear
*- strL 格式的变量不能用来进行 joinby,所以要 recast 下:
recast str12 IPC, force
gen len = strlen(IPC)
replace IPC = ustrregexs(0) if ustrregexm(IPC, ".{5,6}/.{2}") & len > 12
replace len = strlen(IPC)
tab len
drop len
forval l = 3/12 {
preserve
replace IPC = substr(IPC, 1, `l')
joinby IPC using res1/`l'
save res2/`l', replace
restore
}
*- 合并
use res2/3, clear
forval l = 4/12 {
append using res2/`l'
}
count if 正则表达式 == "1==1"
drop len IPC
duplicates drop ipzlid myid, force
save 初步筛选结果, replace
这样就完成了初步筛选。
筛选符合关键词条件的专利
再把标题和关键词信息合并进来:
use 初步筛选结果, clear
tostring ipzlid, replace format(%16.0f)
merge m:1 ipzlid using 2010年专利申请数据.dta
drop if _m == 2
drop _m
egen expgroup = group(正则表达式)
codebook expgroup
*> ----------------------------------------------------------------------------------
*> expgroup group(正则表达式)
*> ----------------------------------------------------------------------------------
*>
*> Type: Numeric (float)
*>
*> Range: [1,79] Units: 1
*> Unique values: 79 Missing .: 0/250,983
*>
*> Mean: 37.4997
*> Std. dev.: 22.5094
*>
*> Percentiles: 10% 25% 50% 75% 90%
*> 3 19 37 53 66
replace 标题 = strupper(标题)
replace 摘要 = strupper(摘要)
replace 标题 = subinstr(标题, " ", "", .)
replace 摘要 = subinstr(摘要, " ", "", .)
gen text = 标题 + " " + 摘要
drop 标题 摘要
ren IPC 分类号
save 初步筛选结果2, replace
循环进行筛选:
cap mkdir "res3"
use 初步筛选结果2, clear
forval i = 1/79 {
di "`i'"
preserve
keep if expgroup == `i'
qui cap {
keep if `=正则表达式[1]'
save res3/`i', replace
}
restore
}
对于那些没有得到任何结果的表达式要进行仔细检查,例如这里发现 10 号表达式有问题:
replace 正则表达式 = `"ustrregexm(text, "((((煤|COAL)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING))|((采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(煤|COAL)))&(节能|节碳|节约|绿色|低碳|SAV\w*\b|ENERGY|ECONOMIZ\w*\b|RETRENCH\w*\b|RECYCL\w*\b|CLEAN\w*\b|SUBSTITUT\w*\b|ALTERNATIVE|GREEN|(减排|减碳|((LOW\w*\b|REDUC\w*\b)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))CARBON)|(CARBON((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(LOW\w*\b|REDUC\w*\b)))))")"' if 正则表达式 == `"ustrregexm(text, "(((煤|COAL)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING))|"'
使用修正后的结果再运行:
use 初步筛选结果2, clear
replace 正则表达式 = `"ustrregexm(text, "((((煤|COAL)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING))|((采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(煤|COAL)))&(节能|节碳|节约|绿色|低碳|SAV\w*\b|ENERGY|ECONOMIZ\w*\b|RETRENCH\w*\b|RECYCL\w*\b|CLEAN\w*\b|SUBSTITUT\w*\b|ALTERNATIVE|GREEN|(减排|减碳|((LOW\w*\b|REDUC\w*\b)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))CARBON)|(CARBON((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(LOW\w*\b|REDUC\w*\b)))))")"' if 正则表达式 == `"ustrregexm(text, "(((煤|COAL)((.{0,2})|((?:\s*\b\w+\b\s*){0,2}))(采|矿|井|EXCAVAT\w*\b|MINE|MINING|PRODUCTING))|"'
keep if expgroup == 10
keep if `=正则表达式[1]'
save res3/10, replace
不过这里还是没有得到结果。
合并所有的:
use res3/1, clear
forval y = 2/79 {
append using res3/`y'
}
keep ipzlid 技术分支编号
duplicates drop _all, force
save 2010绿色专利筛选结果, replace
list in 1/10
*> +----------------------+
*> | ipzlid 技术~号 |
*> |----------------------|
*> 1. | 2010000271 8.2.2 |
*> 2. | 2010000272 8.2.2 |
*> 3. | 2010000273 8.2.2 |
*> 4. | 2010000274 8.2.2 |
*> 5. | 2010000275 8.2.2 |
*> |----------------------|
*> 6. | 2010000276 8.2.2 |
*> 7. | 2010000278 8.2.2 |
*> 8. | 2010000279 8.2.2 |
*> 9. | 2010000280 8.2.2 |
*> 10. | 2010000281 8.2.2 |
*> +----------------------+
这样我们就完成了该年的绿色专利筛选。
最后我们再统计各个类别的申请占比:
use 专利分类号筛选标准.dta, clear
keep if strlen(技术分支编号) == 1
keep 技术分支*
save classdf, replace
use 2010绿色专利筛选结果, clear
replace 技术分支编号 = substr(技术分支编号, 1, 1)
merge m:1 技术分支编号 using classdf
contract 技术分支名称
gr pie _freq, over(技术分支名称) ///
plabel(_all percent, format(%6.2f)) ///
ti("2010 年绿色技术专利各类别申请占比") ///
subti("数据处理:微信公众号 RStata") ///
caption("数据来源:国家知识产权局")
gr export pic7.png, width(4800) replace
不过需要注意的是,专利数据中同时包含了申请和授权信息,因此统计数量前需要先去重,这个可以阅读专利数据的介绍:
1985~2024 年专利申请与授权数据(版本 3,含申请人所处的省市区县):https://rstata.duanshu.com/#/brief/course/2397451274c546d3a36e156ffc865988
这里由于没有公开公告号变量,所以没有这么做。
如何参加课程?
购买 RStata 名师讲堂会员都可以参加这个课程啦!
详情可阅读这篇推文:数据处理、图表绘制、效率分析与计量经济学如何学习~,更多关于 RStata 培训班的信息可添加微信号 r_stata 咨询(上图中有二维码)。
会员购买:从首页的会员卡专区即可查看和购买会员卡 https://rstata.duanshu.com/#/card/list/
课程主页(点击文末的阅读原文即可跳转):
https://rstata.duanshu.com/#/brief/course/66607ec05c3748699883f5e834682125