上次课程中我们计算了上市公司专利与其引用专利的文本相似度。今天我们继续上次课的内容,筛选颠覆性创新专利。
「企业数字化转型与颠覆性技术创新——来自专利网络与SBERT模型的微观证据_黄先海」文献中,作者定义专利的创新度为其与所有引用专利相似度平均值的倒数(取对数):

也就是和引用专利的相似度越低,创新度越高。
然后定义突破性技术创新的专利为:同年同一行业企业的专利中,创新度位于前 20% 的专利。重要影响力技术创新的专利为:同年同一行业企业的专利中,3 年内被引次数排名前 20% 的专利。
同时满足上述两个条件的专利即位具有颠覆性创新的。

在处理前仅保留发明专利并且删除金融和保险类企业。
计算专利创新度
因此我们首先计算专利的创新度。
2021年上市公司专利与其引用专利的相似度计算结果.dta 文件是按照上次课程内容计算的结果:
library(tidyverse) haven::read_dta("2021年上市公司专利与其引用专利的相似度计算结果.dta") %>% distinct(newipzlid, newipzlid2, .keep_all = T) -> dfall
dfall
|
其实在上次课程中的计算过程中可以先对“专利对”进行去重后再计算,可以节省很多运算量。
匹配上市公司信息:
read_rds("2001年上市公司专利引用信息.rds") -> df0
df0 %>% select(股票代码, newipzlid, newipzlid2) %>% left_join(dfall) -> dfall
dfall
|
根据创新度公式计算每个专利的创新度:
dfall %>% group_by(股票代码, newipzlid) %>% summarise(Innov = log(n() / sum(similarity))) %>% ungroup() -> innovdf
innovdf
|
不过暂时我们还不能直接继续后面的步骤,因为这里没有涵盖全部的,也就是没有引用的专利不在其中,这些专利的创新度其实就是 0。
读取全部 2021 年上市公司发明专利
readr::read_csv("2001年上市公司与发明专利数据匹配结果.csv") -> df0a
df0a
|
在专利数据的介绍里面我们提到了,专利数据里面有重复的,一种去重方法就是去除公开公告号结尾的字母之后再去重。不过这里我们不能直接去重,而是要优先保留 innovdf 里面的专利:
df0a %>% left_join(innovdf %>% select(newipzlid) %>% distinct() %>% mutate(class = 1)) %>% mutate(class = if_else(is.na(class), 0, class)) %>% mutate(公开公告号 = str_remove(公开公告号, "[A-Z]$")) %>% group_by(股票代码, 公开公告号) %>% filter(class == max(class, na.rm = T)) %>% select(-class) %>% ungroup() %>% distinct(股票代码, 公开公告号, .keep_all = T) -> df0b
df0b
|
筛选突破性技术创新专利
同年同一行业企业的专利中,创新度位于前 20% 的专利。
因此这里我们还需要上市公司的行业信息。这里我们使用证监会行业分类,这个变量在之前分享的这个数据里面有:
2000~2024 年上市公司注册地址与办公地址(含经纬度及其所处的省市区县):https://rstata.duanshu.com/#/brief/course/746d4f595eba41a2a116b5a6edc3ac0a
IndustryName [行业名称] - 2023年(含)之后的年份是按照中国上市公司协会行业分类, 2012年(含)之后的年份是按照2012版证监会行业分类,2012年之前是按照2001版证监会行业分类。如:2012年证监会行业分类是根据统计截止日期与证监会2012版本披露的实施日期,用2012版本的行业填充。
附件中提供了 2001 年的数据:
haven::read_dta("2001年上市公司行业信息.dta") -> df1
df1 %>% select(股票代码, 行业名称, 年份) %>% distinct() -> industrydf
industrydf
df1 %>% select(股票代码, 行业名称2 = 行业名称) %>% distinct(股票代码, .keep_all = T) -> industrydf2
industrydf2
|
如果跨年处理的话,这里其实会遇到同一家公司在不同年份的行业不同。所以我准备了两个行业数据,一个是各年各公司的行业信息,另外一个则是每个公司的行业(不分行业,粗暴的去重),这样如果和第一个匹配成功的就用第一个的结果,第一个没有匹配成功的用第二个的结果。
df0b %>% select(股票代码, newipzlid) %>% left_join(innovdf) %>% mutate(Innov = if_else(is.na(Innov), 0, Innov), 年份 = as.numeric(str_sub(format(newipzlid, scientific = FALSE, trim = TRUE), 1, 4))) %>% filter(Innov > 0) %>% left_join(industrydf) %>% left_join(industrydf2) %>% mutate(行业名称 = if_else(is.na(行业名称), 行业名称2, 行业名称)) %>% filter(!is.na(行业名称)) -> df2a
df2a
|
可以看到这里我又把创新度为 0 的删除了。这其实是因为最开始我准备用所有的专利数据计算 80% 分位数进行筛选,但是后来发现创新度为 0 的太多,基于所有专利技术的 80% 分位数不能有效的筛选,所以到这里我还是把创新度为 0 的删除了。
计算分位数:
df2a %>% select(-行业名称2) %>% group_by(年份, 行业名称) %>% summarise(p80 = quantile(Innov, probs = 0.8)) %>% ungroup() -> df2b
df2a %>% select(-行业名称2) %>% left_join(df2b) %>% filter(Innov >= p80) -> df2c
df2c
|
这些专利就是具有突破性技术创新的专利了。
重要影响力技术创新专利
同年同一行业企业的专利中,3 年内被引次数排名前 20% 的专利。
这里需要使用每个专利在特定窗口内的被引用次数,之前平台上有分享过这个数据:
1985~2024 年各专利当年~十一年内的被自引、被他引数量统计:https://rstata.duanshu.com/#/brief/course/51e62d1eae074a4d8174a3969f5025c6
附件中提供了 2001 年的部分数据:
haven::read_dta("2021年各专利当年~十一年内的被自引、被他引数量统计.dta") -> df3 df3
|
总被引次数 = 总被自引次数 + 总被他引次数,计算每个专利的总被引次数:
df3 %>% select(newipzlid, 三年内) %>% count(newipzlid, wt = 三年内) %>% rename(三年内被引次数 = n) %>% mutate(newipzlid = as.numeric(newipzlid)) -> df3a
df3a
|
分年分行业计算被引用次数的 80% 分位数:
df0b %>% select(股票代码, newipzlid, 年份) %>% left_join(df3a) %>% filter(三年内被引次数 > 0, !is.na(三年内被引次数)) %>% left_join(industrydf) %>% left_join(industrydf2) %>% mutate(行业名称 = if_else(is.na(行业名称), 行业名称2, 行业名称)) %>% filter(!is.na(行业名称)) %>% select(-行业名称2) %>% group_by(年份, 行业名称) %>% summarise(p80b = quantile(三年内被引次数, probs = 0.8)) %>% ungroup() -> df3b
df3b
|
然后再筛选:
df0 %>% select(股票代码, newipzlid, 年份) %>% left_join(df3a) %>% filter(三年内被引次数 > 0, !is.na(三年内被引次数)) %>% left_join(industrydf) %>% left_join(industrydf2) %>% mutate(行业名称 = if_else(is.na(行业名称), 行业名称2, 行业名称)) %>% filter(!is.na(行业名称)) %>% select(-行业名称2) %>% left_join(df3b) %>% filter(三年内被引次数 >= p80b) -> df3c
df3c
|
颠覆性创新专利
取上述两种筛选结果的交集即可得到颠覆性创新专利:
df2c %>% inner_join(df3c) %>% select(股票代码, 年份, newipzlid, 行业名称, 三年内被引次数, 创新度 = Innov, everything()) -> df4
df4 %>% haven::write_dta("2001上市公司颠覆性创新专利筛选结果(SBERT_paraphrase-multilingual-MiniLM-L12-v2模型).dta")
|
再循环所有年份就可以得到全部的上市公司颠覆性创新专利了~
点击这里跳转到 RStata 短书平台获取附件:名师讲堂|突破性创新与颠覆性创新:使用BERT和 SBERT 模型计算专利文本相似度(二)
评论