名师讲堂|使用 Stata 处理上市公司专利互引矩阵及测算上市公司供应链协同创新程度(一)

今天给大家分享一下使用 Stata 处理上市公司专利互引矩阵及测算上市公司供应链协同创新程度指标的方法。

上市公司供应链协同创新程度指标的构造方法是参考附件中的文献「共同股东与供应链协同创新——基于专利互引的视角_汤旭东.pdf」

按照文献介绍的测算思路,第一步我们需要构造一份上市公司互引的数据,然后分别把供应商和客户数据分别和该数据匹配,这样就得到了供应商和客户互引的数据,统计数量就可以得到上市公司供应链协同创新程度指标了。

由于恰好认识作者,根据和作者的沟通,该指标的计算过程需要注意如下事项:

  1. 只测算供应商和客户是上市公司的,非上市公司的不考虑;
  2. 最终的 CoCite 指标是 log(x + 1) 构造的,这样可以确保该指标 > 0。

内容较多,今年我们先讲解如何构造上市公司互引数据,另外恰好最近有小伙伴想构造上市公司互引数量矩阵,我们也顺便讲解下这个。

数据准备

在之前的数据分享中,我们分享了上市公司专利及其引证与被引证信息:

1985~2024 年上市公司专利引证专利的基本信息: https://rstata.duanshu.com/#/course/67563c79c83248c599465fd138868bf9

1985~2024年上市公司专利的被引证专利信息: https://rstata.duanshu.com/#/brief/course/27fb7aa15e8c4c0bab7dc74f4d9745c6

1985~2024 年上市公司与专利数据匹配结果(版本3, 含申请、授权信息): https://rstata.duanshu.com/#/course/04100321f88b411f90429be934934bff

由于数据非常巨大,所以我只保留了本课需要的变量:

use 上市公司专利的引证_sim.dta, clear

use 上市公司专利的被引证_sim.dta, clear

上市公司专利信息我也只保留了所需变量:

use 上市公司与专利数据_sim.dta, clear

理论上来说引证和被引证数据只要使用一个就够了,但是为了尽可能包含所有的引用与被引用信息,我们还是同时使用两个数据,然后合并之后再去除重复的。

分别把引证和被引证信息根据 newipzlid 变量和上市公司专利数据匹配:

*- 引证
use 上市公司专利的引证_sim.dta, clear
ren 公开公告号 公开公告号_被引证的专利
ren IPC IPC_被引证的专利
joinby newipzlid using 上市公司与专利数据_sim.dta
drop 公开公告号 IPC
ren newipzlid newipzlid_被引证的专利
ren 股票代码 股票代码_被引证的专利

ren newipzlid_original newipzlid
joinby newipzlid using 上市公司与专利数据_sim.dta
ren newipzlid newipzlid_原专利
ren 公开公告号 公开公告号_原专利
ren 股票代码 股票代码_原专利
ren IPC IPC_原专利
save data1, replace

*- 被引证
use 上市公司专利的被引证_sim.dta, clear
ren 公开公告号 公开公告号_原专利
ren IPC IPC_原专利
joinby newipzlid using 上市公司与专利数据_sim.dta
drop 公开公告号 IPC
ren 股票代码 股票代码_原专利
ren newipzlid newipzlid_原专利

ren newipzlid_original newipzlid
joinby newipzlid using 上市公司与专利数据_sim.dta
ren newipzlid newipzlid_被引证的专利
ren 股票代码 股票代码_被引证的专利
ren 公开公告号 公开公告号_被引证的专利
ren IPC IPC_被引证专利
save data2, replace

合并两个数据再去除重复的:

use data1, clear
append using data2
duplicates drop newipzlid_原专利 newipzlid_被引证的专利 股票代码_被引证的专利 股票代码_原专利, force
ren (newipzlid_被引证的专利 股票代码_被引证的专利 公开公告号_被引证的专利 IPC_被引证的专利) (newipzlid_被引专利 股票代码_被引专利 公开公告号_被引专利 IPC_被引专利)
order 股票代码* newipzlid* IPC* 公开公告号*
save 上市公司之间专利互引信息, replace

这样我们就得到了上市公司之间的专利互引信息,也就是每一个上市公司的专利引用了哪些其他上市公司的专利。

实际上下一步我们就可以计算供应链协同创新程度了,不过在此之前我们再插入一个内容,就是如何使用目前得到的这个数据构造上市公司之间的互引数量矩阵。

不过统计数量的话就面临一个难题,该如何确定年份,因为原专利对应一个年份,被引专利也对应一个年份,到底用哪个年份?最后思来想去我觉得还是删除年份不一致的最好,因为随着年份的延长,每个专利的被引数量肯定会愈来愈多,就难以比较了,因此可以考虑只计算专利被当年申请的其他专利引用的数量。 也就是计算专利申请当年引用与被引用的数量。

use 上市公司之间专利互引信息, clear
*> (数据处理:微信公众号 RStata)
gen 年份 = substr(newipzlid_原专利, 1, 4)
gen 年份2 = substr(newipzlid_被引专利, 1, 4)
keep if 年份 == 年份2
*> (2,251,011 observations deleted)
drop 年份2
destring 年份, replace
*> 年份: all characters numeric; replaced as int
contract 股票代码* 年份
ren _freq 引用数量
save data3, replace
*> file data3.dta saved
list in 1/10
*> +-------------------------------------+
*> | ~引专利 ~原专利 年份 引用数量 |
*> |-------------------------------------|
*> 1. | 000001 000001 2019 2 |
*> 2. | 000001 000001 2020 5 |
*> 3. | 000001 000001 2021 6 |
*> 4. | 000001 000001 2022 19 |
*> 5. | 000001 000063 2013 1 |
*> |-------------------------------------|
*> 6. | 000001 000651 2019 2 |
*> 7. | 000001 002415 2019 2 |
*> 8. | 000001 300188 2019 4 |
*> 9. | 000001 300872 2019 4 |
*> 10. | 000001 301236 2020 2 |
*> +-------------------------------------+

然后接下来的难点就是如何根据这个引用信息数量表得到矩阵了。其中矩阵里面的每个元素是 A 公司引用 B 公司的数量 + B 公司引用 A 公司的数量。

我们先构造一个平衡面板:

*- 年份列表
keep 年份
duplicates drop 年份, force
*> Duplicates in terms of 年份
*> (30,863 observations deleted)
gsort 年份
save yearlist, replace
*> file yearlist.dta saved
*- 股票代码列表
use data3, clear
*> (数据处理:微信公众号 RStata)
keep 股票代码*
gen id = _n
gather 股票代码*
*> id
keep value
duplicates drop value, force
*> Duplicates in terms of value
*> (57,745 observations deleted)
ren value 股票代码
save codelist, replace
*> file codelist.dta saved

使用 cross using 构造平衡面板:

use codelist, clear
*> (数据处理:微信公众号 RStata)
ren 股票代码 股票代码_原专利
cross using codelist
ren 股票代码 股票代码_被引专利

理论上可以再 cross using yearlist 来构造含有年份的平衡面板,但是这会得到一个无比庞大的数据集,所以我们还是一年年来,这里仅演示 2020 年的:

gen 年份 = 2020
*- 匹配原专利引用被引专利的数量
merge 1:1 股票代码_原专利 股票代码_被引专利 年份 using data3
*> Result Number of obs
*> -----------------------------------------
*> Not matched 16,371,091
*> from master 16,343,023 (_merge==1)
*> from using 28,068 (_merge==2)
*> Matched 2,826 (_merge==3)
*> -----------------------------------------
drop if _m == 2
*> (28,068 observations deleted)
drop _m
list in 1/10
*> +-------------------------------------+
*> | ~原专利 ~引专利 年份 引用数量 |
*> |-------------------------------------|
*> 1. | 000001 000001 2020 5 |
*> 2. | 000001 000002 2020 . |
*> 3. | 000001 000008 2020 . |
*> 4. | 000001 000012 2020 . |
*> 5. | 000001 000016 2020 . |
*> |-------------------------------------|
*> 6. | 000001 000021 2020 . |
*> 7. | 000001 000026 2020 . |
*> 8. | 000001 000030 2020 . |
*> 9. | 000001 000032 2020 . |
*> 10. | 000001 000035 2020 . |
*> +-------------------------------------+

然后我们分别匹配 股票代码_原专利 引用 股票代码_被引专利 的数量以及反过来的数量:

*- 匹配被引专利
ren 股票代码_原专利 temp
ren 股票代码_被引专利 股票代码_原专利
ren temp 股票代码_被引专利
ren 引用数量 value1
merge 1:1 股票代码_原专利 股票代码_被引专利 年份 using data3
*> Result Number of obs
*> -----------------------------------------
*> Not matched 16,371,091
*> from master 16,343,023 (_merge==1)
*> from using 28,068 (_merge==2)
*> Matched 2,826 (_merge==3)
*> -----------------------------------------
drop if _m == 2
*> (28,068 observations deleted)
drop _m
ren 引用数量 被引用数量
ren value1 引用数量
*- 再把名字换过来
ren 股票代码_原专利 temp
ren 股票代码_被引专利 股票代码_原专利
ren temp 股票代码_被引专利
replace 引用数量 = 0 if mi(引用数量)
*> (16,343,023 real changes made)
replace 被引用数量 = 0 if mi(被引用数量)
*> (16,343,023 real changes made)
*- 自引的就不加总了
replace 被引用数量 = 0 if 股票代码_原专利 == 股票代码_被引专利
*> (1,056 real changes made)
gen 互引数量 = 引用数量 + 被引用数量
save 2020年上市公司间互引数量矩阵, replace
*> file 2020年上市公司间互引数量矩阵.dta saved
list in 1/10
*> +----------------------------------------------------------+
*> | ~原专利 ~引专利 年份 引用数量 被引~量 互引数量 |
*> |----------------------------------------------------------|
*> 1. | 000001 000001 2020 5 0 5 |
*> 2. | 000002 000001 2020 0 0 0 |
*> 3. | 000008 000001 2020 0 0 0 |
*> 4. | 000012 000001 2020 0 0 0 |
*> 5. | 000016 000001 2020 0 0 0 |
*> |----------------------------------------------------------|
*> 6. | 000021 000001 2020 0 0 0 |
*> 7. | 000026 000001 2020 0 0 0 |
*> 8. | 000030 000001 2020 0 0 0 |
*> 9. | 000032 000001 2020 0 0 0 |
*> 10. | 000035 000001 2020 0 0 0 |
*> +----------------------------------------------------------+

这样我们就得到了 2020 年的上市公司间互引数量矩阵,当然这个是长数据模式,可以使用下面的代码转换成矩阵(宽数据):

use 2020年上市公司间互引数量矩阵, clear
replace 股票代码_被引专利 = "_" + 股票代码_被引专利
drop 年份 引用数量 被引用数量
gsort 股票代码_原专利 股票代码_被引专利
spread 股票代码_被引专利 互引数量

不过因为这个矩阵太大了,使用 Stata 执行这个操作是非常慢的,可以考虑使用 R 语言帮个忙:

library(tidyverse)
haven::read_dta("~/Desktop/使用 Stata 处理上市公司专利互引矩阵及测算上市公司供应链协同创新程度(一)/2020年上市公司间互引数量矩阵.dta") -> df

df %>%
select(-年份, -引用数量, -被引用数量) %>%
arrange(股票代码_原专利, 股票代码_被引专利) %>%
spread(股票代码_被引专利, 互引数量) %>%
rename_at(vars(!contains("_")), ~paste0("_", .x)) -> df2

df2

#> # A tibble: 4,043 × 4,044
#> 股票代码_原专利 `_000001` `_000002` `_000008` `_000012` `_000016` `_000021`
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 000001 5 0 0 0 0 0
#> 2 000002 0 0 0 0 0 0
#> 3 000008 0 0 0 0 0 0
#> 4 000012 0 0 0 0 0 0
#> 5 000016 0 0 0 0 2 0
#> 6 000021 0 0 0 0 0 0
#> 7 000026 0 0 0 0 0 0
#> 8 000030 0 0 0 0 0 0
#> 9 000032 0 0 0 0 0 0
#> 10 000035 0 0 0 0 0 0
#> # ℹ 4,033 more rows
#> # ℹ 4,037 more variables: `_000026` <dbl>, `_000030` <dbl>, `_000032` <dbl>,
#> # `_000035` <dbl>, `_000039` <dbl>, `_000050` <dbl>, `_000055` <dbl>,
#> # `_000059` <dbl>, `_000060` <dbl>, `_000063` <dbl>, `_000065` <dbl>,
#> # `_000066` <dbl>, `_000070` <dbl>, `_000089` <dbl>, `_000090` <dbl>,
#> # `_000100` <dbl>, `_000157` <dbl>, `_000158` <dbl>, `_000333` <dbl>,
#> # `_000338` <dbl>, `_000400` <dbl>, `_000404` <dbl>, `_000410` <dbl>, …

df2 %>%
haven::write_dta("上市公司互引数量矩阵.dta", label = "数据处理:微信公众号 RStata")

这样我们就解决了这个问题。下次课我们将继续讲解如何进一步计算上市公司供应链协同创新程度。

点击这里跳转到 RStata 短书平台获取附件:名师讲堂|使用 Stata 处理上市公司专利互引矩阵及测算上市公司供应链协同创新程度(一)

评论