名师讲堂|使用 R 语言测算数实融合水平(二):基于真实专利数据

继续上次的内容,今天我们再来学习如何基于真实专利数据计算数实融合水平。

仿照示例数据,我们这里也需要准备三份数据:

  1. 专利的 IPC 分类号;
  2. IPC 与国民经济行业的对照;
  3. 数字经济与实体经济的行业分类。

准备专利数据

首先我们准备专利的 IPC 分类号数据。专利的原始数据可以从之前分享的这里下载:

1985~2024 年专利申请与授权数据(版本 3,含申请人所处的省市区县):https://rstata.duanshu.com/#/brief/course/2397451274c546d3a36e156ffc865988

原始数据非常大,我们仅仅保留需要的,由于提供的专利数据是 dta 格式的,所以还是使用 Stata 读取处理更快速。

cap mkdir "patent_small"
forval y = 1985/2024 {
use "/Volumes/C16T/大数据/newIP专利数据分年/`y'", clear
*- 去除重复的专利
replace 公开公告号 = ustrregexs(1) if ustrregexm(公开公告号, "(.*)[A-Z]$")
duplicates drop 年份 公开公告号, force
duplicates drop 年份 申请号, force
keep newipzlid 年份 IPC 省 省代码 市 市代码 县 县代码
export delimited using patent_small/`y'.csv, replace
}

不过由于部分年份的专利数据非常大,所以大家的电脑可能无法直接运行上面的循环。不过也可以通过每次读取部分行来解决:

Stata 读取数据的大小受到电脑内存的限制,因此对于超大文件可以通过下面的方式读取:

use 命令有种用法是:

use [varlist] [if] [in] using filename [, clear nolabel]

例如每次读 100 条:use in 1/100 using 文件名.dta, clear

不过读取最后一部分的时候需要知道文件的总行数。

获取文件的总行数可以使用 describe 命令,该命令有种用法是:

describe [varlist] using filename [, file_options]

例如获取某个名为 2012.dta 数据的总行数:

desc using 2012.dta

由于全部年份的数据非常大,所以附件中只提供了 2012 的:patent_small2/2012.csv

按照参考文献的方法,删除只有一个 IPC 号的专利,然后每个专利的分类号只使用前 10 个:

准备专利 IPC 数据

library(tidyverse)
library(readxl)
library(haven)
# 1. 处理专利 IPC 数据
# 读取专利数据
patent_data <- read_csv("patent_small/2012.csv") %>%
filter(str_detect(IPC, ";")) %>%
select(newipzlid, IPC) %>%
mutate(IPC = str_replace_all(IPC, " ", "")) %>%
mutate(
ipc_list = str_split(IPC, ";"),
ipc = map_chr(ipc_list, ~ paste(head(.x, 10), collapse = ";"))
) %>%
select(newipzlid, ipc)

patent_data
#> # A tibble: 466,947 × 2
#> newipzlid ipc
#> <dbl> <chr>
#> 1 20120565869 G06F19/00;G01R29/08
#> 2 20120196633 G01S7/40;G01R29/02
#> 3 20120195174 G06F21/62;G06F12/14
#> 4 20121092201 H04L29/06;G01R31/00
#> 5 20120565160 B23P9/04;C21D7/04
#> 6 20120565868 G06F17/00;G08G5/04;G01C21/00
#> 7 20121034880 G01H11/06;H04R1/44
#> 8 20120554752 B01J13/02;C08K5/10;C08J7/04;C23F11/00
#> 9 20121681282 G01M9/04;F25D17/02
#> 10 20120565870 G06F17/00;G01C21/00
#> # ℹ 466,937 more rows

IPC 与 国民经济行业小类对照

这里我们使用的是「国际专利分类与国民经济行业分类参照关系表(2018)」,该文件下载自国家知识产权局官网。首先我们需要借助外部工具把 pdf 文件转换成 xlsx 文件,我使用的是 Adobe Acrobat。

处理整齐:

# 此处代码需下载讲义材料查看~

uniq_ipc.dta 数据是历年所有专利涉及的 IPC 分类号。例如 2012 年的可以这么处理得到:

patent_data %>%
select(ipc) %>%
distinct() %>%
mutate(ipc_split = str_split(ipc, ";")) %>%
unnest(ipc_split) %>%
rename(uniq_ipc = ipc_split) %>%
select(uniq_ipc) %>%
distinct()
#> # A tibble: 45,547 × 1
#> uniq_ipc
#> <chr>
#> 1 G06F19/00
#> 2 G01R29/08
#> 3 G01S7/40
#> 4 G01R29/02
#> 5 G06F21/62
#> 6 G06F12/14
#> 7 H04L29/06
#> 8 G01R31/00
#> 9 B23P9/04
#> 10 C21D7/04
#> # ℹ 45,537 more rows

附件中我给大家提前生成好了历年所有专利涉及的 IPC 分类号:

haven::read_dta("uniq_ipc.dta") -> expanded_ipc
expanded_ipc
#> # A tibble: 85,187 × 1
#> uniq_ipc
#> <chr>
#> 1 A47G21/10
#> 2 A47G21/00
#> 3 B28B3/22
#> 4 B28B3/20
#> 5 B22D11/06
#> 6 B22D11/10
#> 7 B22D11/18
#> 8 A47L13/24
#> 9 A47L13/20
#> 10 G02B21/14
#> # ℹ 85,177 more rows

下面我们需要给每个 IPC 对应上行业小类:

# 4. 处理 IPC 对照表,按长度分类
industry_ipc_clean %>%
rename(IPC = 国际专利分类号) %>%
mutate(
IPC = str_replace_all(IPC, "[* ]", ""),
len = str_length(IPC)
) -> ipc_reference

# 5. IPC 数据与对照表匹配
lapply(3:11, function(i){
ipc_reference %>%
filter(len == i) %>%
select(-len) -> len_data

expanded_ipc %>%
mutate(IPC = str_sub(uniq_ipc, 1, i)) %>%
inner_join(len_data, by = "IPC", relationship = "many-to-many") %>%
select(uniq_ipc, 国民经济行业代码)
}) %>%
bind_rows() %>%
distinct(uniq_ipc, 国民经济行业代码) -> all_matched

write_dta(all_matched, "专利数据与行业小类代码简易对照表.dta")

可以看到这个数据的格式其实就类似上次课说的:IPC与产业对照表_示例2.dta

数字经济产业与实体产业

按照论文的介绍,实体产业包括下面四类:

  • 制造业
  • 农业
  • 建筑业及其他工业
  • 服务业
# 6. 定义实体产业分类
industry_ipc_clean %>%
mutate(
行业门类 = str_sub(国民经济行业代码, 1, 1),
实体产业 = case_when(
行业门类 == "C" ~ "制造业",
行业门类 == "A" ~ "农业",
行业门类 %in% c("B", "D", "E") ~ "建筑业及其他工业",
行业门类 %in% c("I", "O") ~ "服务业",
TRUE ~ ""
)
) %>%
filter(实体产业 != "") %>%
select(国民经济行业代码, 实体产业) %>%
distinct() -> entity_industry

write_dta(entity_industry, "实体产业分类.dta")

这里其实论文里面说的有些含糊,例如农业到底是特指 A01 还是 A,也就是农林牧渔?

数字经济产业分类使用的是「数字经济及其核心产业统计分类(2021)」,该文件也是来源于国家知识产权局。

library(tidyverse)
library(docxtractr)

# 读取 docx 文件
doc <- read_docx("数字经济及其核心产业统计分类(2021).docx")

# 提取表格数据
doc %>%
docx_extract_all_tbls() %>%
.[[1]] %>%
slice(-1, -2) %>%
set_names("大类", "中类", "小类", "名称", "说明", "国民经济行业代码及名称") %>%
type_convert() %>%
mutate(国民经济行业代码 = str_extract(国民经济行业代码及名称, "\\d{4}")) %>%
haven::write_dta("数字经济及其核心产业统计分类.dta")

然后再处理:

# 7. 处理数字经济核心产业
read_dta("数字经济及其核心产业统计分类.dta") %>%
filter(!is.na(小类), 小类 != "") %>%
filter(str_sub(小类, 1, 2) != "05") %>%
select(国民经济行业代码及名称, 小类) -> digital_economy

digital_economy
#> # A tibble: 114 × 2
#> 国民经济行业代码及名称 小类
#> <chr> <chr>
#> 1 3911 计算机整机制造 010101
#> 2 3912 计算机零部件制造 010102
#> 3 3913 计算机外围设备制造 010103
#> 4 3914 工业控制计算机及系统制造 010104
#> 5 3915 信息安全设备制造 010105
#> 6 3919 其他计算机制造 010106
#> 7 3921 通信系统设备制造 010201
#> 8 3922 通信终端设备制造 010202
#> 9 3940 雷达及配套设备制造 010203
#> 10 3931 广播电视节目制作及发射设备制造 010301
#> # ℹ 104 more rows
# 提取行业代码
digital_economy %>%
mutate(
v1 = str_extract(国民经济行业代码及名称, "\\d{4}"),
国民经济行业代码及名称 = str_remove(国民经济行业代码及名称, v1),
v2 = str_extract(国民经济行业代码及名称, "\\d{4}"),
国民经济行业代码及名称 = str_remove(国民经济行业代码及名称, v2),
v3 = str_extract(国民经济行业代码及名称, "\\d{4}"),
国民经济行业代码及名称 = str_remove(国民经济行业代码及名称, v3),
v4 = str_extract(国民经济行业代码及名称, "\\d{4}"),
国民经济行业代码及名称 = str_remove(国民经济行业代码及名称, v4)
) %>%
mutate(
数字经济产业 = case_when(
str_sub(小类, 1, 2) == "01" ~ "数字产品制造业",
str_sub(小类, 1, 2) == "02" ~ "数字产品服务业",
str_sub(小类, 1, 2) == "03" ~ "数字技术应用业",
str_sub(小类, 1, 2) == "04" ~ "数字要素驱动业",
TRUE ~ ""
)
) %>%
select(v1, v2, v3, v4, 数字经济产业) %>%
pivot_longer(cols = c(v1, v2, v3, v4), names_to = "var", values_to = "industry2") %>%
filter(!is.na(industry2)) %>%
select(industry2, 数字经济产业) %>%
distinct() -> digital_economy_clean

write_dta(digital_economy_clean, "数字经济核心产业.dta")

然后就可以区分数字与实体了:

# 8. 区分数字与实体产业
industry_ipc_clean %>%
select(国民经济行业代码) %>%
distinct() %>%
mutate(industry2 = str_sub(国民经济行业代码, 2, -1)) %>%
left_join(digital_economy_clean, by = "industry2") %>%
left_join(entity_industry, by = "国民经济行业代码") %>%
select(国民经济行业代码, 数字经济产业, 实体产业) %>%
mutate(class = as.numeric(!is.na(数字经济产业))) %>%
group_by(国民经济行业代码) %>%
summarize(class = sum(class)) %>%
mutate(
类别 = ifelse(class > 0, "数字经济产业", "实体产业")
) %>%
select(国民经济行业代码, 类别) -> industry_classification

industry_classification %>%
count(类别)
#> # A tibble: 2 × 2
#> 类别 n
#> <chr> <int>
#> 1 实体产业 732
#> 2 数字经济产业 89
write_dta(industry_classification, "产业数实分类.dta")

这里感觉论文里面说的也比较含糊,所以我采取的方案是如果该小类同时属于数字和实体,那么该小类就归类为数字经济行业。

计算 IPC 融合矩阵

# 专利数据
patent_data
#> # A tibble: 466,947 × 2
#> newipzlid ipc
#> <dbl> <chr>
#> 1 20120565869 G06F19/00;G01R29/08
#> 2 20120196633 G01S7/40;G01R29/02
#> 3 20120195174 G06F21/62;G06F12/14
#> 4 20121092201 H04L29/06;G01R31/00
#> 5 20120565160 B23P9/04;C21D7/04
#> 6 20120565868 G06F17/00;G08G5/04;G01C21/00
#> 7 20121034880 G01H11/06;H04R1/44
#> 8 20120554752 B01J13/02;C08K5/10;C08J7/04;C23F11/00
#> 9 20121681282 G01M9/04;F25D17/02
#> 10 20120565870 G06F17/00;G01C21/00
#> # ℹ 466,937 more rows
# 此处代码需下载讲义材料查看~

计算行业共现矩阵

分别使用 ipc 匹配各自的行业即可:

# 10. 匹配行业小类
ipc_matrix %>%
rename(uniq_ipc = ipc1) %>%
left_join(all_matched, by = "uniq_ipc", relationship = "many-to-many") %>%
rename(industry1 = 国民经济行业代码) %>%
select(-uniq_ipc) %>%
rename(uniq_ipc = ipc2) %>%
left_join(all_matched, by = "uniq_ipc", relationship = "many-to-many") %>%
rename(industry2 = 国民经济行业代码) %>%
select(-uniq_ipc) %>%
filter(!is.na(industry1) & !is.na(industry2)) %>%
mutate(value = ifelse(industry1 == industry2, 0, value)) %>%
group_by(industry1, industry2) %>%
summarize(value = sum(value), .groups = "drop") %>%
filter(!is.na(industry1) & !is.na(industry2)) -> industry_matrix

industry_matrix
#> # A tibble: 299,131 × 3
#> industry1 industry2 value
#> <chr> <chr> <dbl>
#> 1 A0111 A0111 0
#> 2 A0111 A0112 3858
#> 3 A0111 A0113 3858
#> 4 A0111 A0119 3856
#> 5 A0111 A0121 3856
#> 6 A0111 A0122 3856
#> 7 A0111 A0123 3861
#> 8 A0111 A0131 3859
#> 9 A0111 A0132 3856
#> 10 A0111 A0133 3856
#> # ℹ 299,121 more rows
write_dta(industry_matrix, "industrymat.dta")

计算数实融合

然后就可以计算数实融合水平了:

# 此处代码需下载讲义材料查看~

由此我们便计算得到了 2012 年的数实融合水平,不过这个结果比参考文献的大挺多,但是仔细检查了很多遍也没发现计算过程的问题,也有可能是原作者的一些处理细节我我的不一样。

循环各年的就可以计算得到各年的结果了。下次课我们再讲解如何计算分城市和产业的~

点击这里跳转到 RStata 短书平台获取附件:名师讲堂|使用 R 语言测算数实融合水平(二):基于真实专利数据

评论