名师讲堂|使用 Stata 测算数实融合水平(二)

教育   2024-10-21 09:57   安徽  


为了让大家更好理解本文的内容,欢迎各位名师讲堂会员参加明晚 8 点的直播课:「使用 Stata 测算数实融合水平(二)」

购买名师讲堂会员:https://rstata.duanshu.com/#/card/6c8dc065c753498e948c45e032a98729 更多详情欢迎添加李老师微信 r_stata 了解:


今天给大家分享一下「新质生产力背景下数实融合的测算与时空比较——基于专利共分类方法的研究」一文中的数实融合水平指标的 Stata 计算方法,不过由于论文中关于指标计算的一些细节描述的较为含糊,所以计算过程中的一些处理方法还有待探讨,感兴趣的小伙伴也可以说说自己的想法。

按照论文的介绍,数实融合水平的测算过程如下所示:

一个简单的示例

准备示例数据

按照上面的示意图。计算数实融合需要下面三个数据:

一是各个专利的分类号:

clear all  
input str2 id str20 ipc 
"P1" "IPC1;IPC3"
"P2" "IPC1;IPC2"
"P3" "IPC1;IPC2;IPC3"
end 
compress 
save 专利示例数据_示例, replace 

二是 IPC 分类号与产业对照表:

clear all  
input str4 uniq_ipc str20 industry
"IPC1" "I1"
"IPC2" "I2;I3"
"IPC3" "I3;I4"
end 
compress 
save IPC与产业对照表_示例, replace 

三是产业分类表:

clear all  
input str4 uniq_industry str20 class
"I1" "数字产业"
"I2" "数字产业"
"I3" "实体产业"
"I4" "实体产业"
end 
compress 
save 产业分类表_示例, replace 

计算 IPC 融合矩阵

根据文献的介绍,IPC 融合矩阵的结果就是如果两个 IPC 号出现在一个专利的分类号上,返回 1,否则返回 0。因此我们可以使用 Mata 的代码循环各个专利,分别获取每个分类号里面的 IPC 组合,合并再统计数量:

use 专利示例数据_示例, clear 
gen _freq = 1 
mata:
    ipc = st_sdata(., "ipc")
    value = st_data(., "_freq"
    fullcombinations = J(0, 3, "")
    for (r = 1; r <= rows(ipc); r++) {
        class_list = colshape(ustrsplit(ipc[r, 1], ";"), 1)
        n_classes = rows(class_list)
        if (n_classes == 2) {
          fullcombinations = fullcombinations \ (class_list[1,1], class_list[2,1], strofreal(value[r,1]))
        }
        if (n_classes > 2) {
          combinations = J(n_classes * n_classes, 3, "")
          row_index = 1
        
          for (i = 1; i <= n_classes; i++) {
              for (j = 1; j <= n_classes; j++) {
                  combinations[row_index, 1] = class_list[i,1]
                  combinations[row_index, 2] = class_list[j,1]
                  combinations[row_index, 3] = strofreal(value[r,1])
                  row_index++
              }
          }
          fullcombinations = fullcombinations \ combinations 
        }
    }

    st_matrix("obs", rows(fullcombinations))
    stata("clear")
    st_addvar("str100""ipc1")
    st_addvar("str100""ipc2")
    st_addvar("str100""value")
    stata("set obs `=obs[1,1]'")
    st_sstore(., ("ipc1""ipc2""value"), fullcombinations)
end 

destringreplace 
compress 
save temp1, replace 

list in 1/10 

*>     +---------------------+
*>     | ipc1   ipc2   value |
*>     |---------------------|
*>  1. | IPC1   IPC3       1 |
*>  2. | IPC1   IPC2       1 |
*>  3. | IPC1   IPC1       1 |
*>  4. | IPC1   IPC2       1 |
*>  5. | IPC1   IPC3       1 |
*>     |---------------------|
*>  6. | IPC2   IPC1       1 |
*>  7. | IPC2   IPC2       1 |
*>  8. | IPC2   IPC3       1 |
*>  9. | IPC3   IPC1       1 |
*> 10. | IPC3   IPC2       1 |
*>     +---------------------+

汇总统计各组合的总共现次数:

use temp1, clear 
collapse (sum) value, by(ipc1 ipc2) 
replace value = 0 if ipc1 == ipc2
save temp1a, replace 

不过这个结果并不是一个对称矩阵,下面我们再把这个数据转换成对称矩阵(对称矩阵转换成长数据就是一个平衡面板):

*- 处理成对称矩阵 
use temp1a, clear 
gen id = _n 
drop value 
gather ipc1 ipc2 
keep value 
duplicates drop value, force 
save temp1b, replace 

ren value value2 
cross using temp1b
ren value ipc1 
ren value2 ipc2 
merge 1:1 ipc1 ipc2 using temp1a 
drop _m 
replace value = 0 if mi(value)
save temp1c, replace 

ren ipc1 temp 
ren ipc2 ipc1 
ren temp ipc2 
ren value value2 
merge 1:1 ipc1 ipc2 using temp1c 
*- 因为对于每个专利,ab ba 的情况都统计了,所以这里选择最大的(统计最全面的)作为共现结果
egen value3 = rowmax(value value2) 
replace value = value3 
drop value2 _m value3 
replace value = 0 if ipc1 == ipc2 
drop if value == 0 
save IPC融合数量计算结果, replace 

list in 1/6, sep(0)
*>     +---------------------+
*>     | ipc1   ipc2   value |
*>     |---------------------|
*>  1. | IPC1   IPC2       2 |
*>  2. | IPC1   IPC3       2 |
*>  3. | IPC2   IPC1       2 |
*>  4. | IPC2   IPC3       1 |
*>  5. | IPC3   IPC1       2 |
*>  6. | IPC3   IPC2       1 |
*>     +---------------------+

转换成矩阵就是这样的:

spread ipc2 value 
list in 1/3 

*>    +---------------------------+
*>    | ipc1   IPC1   IPC2   IPC3 |
*>    |---------------------------|
*> 1. | IPC1      .      2      2 |
*> 2. | IPC2      2      .      1 |
*> 3. | IPC3      2      1      . |
*>    +---------------------------+

然后我们把 IPC 分类号和 IPC与产业对照表 进行匹配,进而将 IPC 替换成产业分类编号:

use IPC融合数量计算结果, clear 
ren ipc1 uniq_ipc
ren ipc2 uniq_ipc2
merge m:1 uniq_ipc using IPC与产业对照表_示例
drop if _m == 2 
drop _m 
ren industry industry1 
drop uniq_ipc 

ren uniq_ipc2 uniq_ipc 
merge m:1 uniq_ipc using IPC与产业对照表_示例
drop if _m == 2 
drop _m 
ren industry industry2 
drop uniq_ipc 

order industry*
foreach i of varlist _all {
  cap format `i' %10s 
}
drop if mi(industry1) | mi(industry2) 

drop if industry1 == ";"
replace industry1 = subinstr(industry1, ";"" ", .)
replace industry1 = strtrim(industry1)
replace industry1 = subinstr(industry1, " "";", .)

drop if industry2 == ";"
replace industry2 = subinstr(industry2, ";"" ", .)
replace industry2 = strtrim(industry2)
replace industry2 = subinstr(industry2, " "";", .)
save temp2, replace 

list, sep(0)

*>     +-----------------------------+
*>     | indust~1   indust~2   value |
*>     |-----------------------------|
*>  1. |    I2;I3         I1       2 |
*>  2. |    I3;I4         I1       2 |
*>  3. |       I1      I2;I3       2 |
*>  4. |    I3;I4      I2;I3       1 |
*>  5. |       I1      I3;I4       2 |
*>  6. |    I2;I3      I3;I4       1 |
*>     +-----------------------------+

计算产业融合矩阵

使用类似上面的 Mata 代码就可以计算产业融合矩阵了:

use temp2, clear 
collapse (sum) value, by(industry1 industry2) 
mata:
  mata clear 
  fullcombinations = J(0, 3, "")
  value = st_data(., "value")
  // industry 矩阵
  industry1 = st_sdata(., "industry1")
  industry2 = st_sdata(., "industry2")

  for (z = 1; z <= rows(industry1); z++) {
    a = ustrsplit(industry1[z,1], ";")
    b = ustrsplit(industry2[z,1], ";")
    combinations = J(cols(a) * cols(b), 3, "")
    row_index = 1
    for (i = 1; i <= cols(a); i++) {
      for (j = 1; j <= cols(b); j++) {
        combinations[row_index, 1] = a[1, i]
        combinations[row_index, 2] = b[1, j]
        combinations[row_index, 3] = strofreal(value[z,1]) 
        row_index++
      }
    }
    fullcombinations = fullcombinations \ combinations 
  }
  st_matrix("obs", rows(fullcombinations))
  stata("clear")
  st_addvar("str100""industry1")
  st_addvar("str100""industry2")
  st_addvar("str100""value")
  stata("set obs `=obs[1,1]'")
  st_sstore(., ("industry1""industry2""value"), fullcombinations)
end 
destringreplace 
compress 
collapse (sum) value, by(industry1 industry2)
save temp3, replace 

list, sep(0)

*>     +-----------------------------+
*>     | indust~1   indust~2   value |
*>     |-----------------------------|
*>  1. |       I1         I2       2 |
*>  2. |       I1         I3       4 |
*>  3. |       I1         I4       2 |
*>  4. |       I2         I1       2 |
*>  5. |       I2         I3       1 |
*>  6. |       I2         I4       1 |
*>  7. |       I3         I1       4 |
*>  8. |       I3         I2       1 |
*>  9. |       I3         I3       2 |
*> 10. |       I3         I4       1 |
*> 11. |       I4         I1       2 |
*> 12. |       I4         I2       1 |
*> 13. |       I4         I3       1 |
*>     +-----------------------------+

然后我们统计下数字产业和实体产业的数量:

use temp3, clear 
gen id = _n 
drop value 
gather industry1 industry2 
keep value
duplicates drop _all, force 
save temp3a, replace 

ren value uniq_industry
save temp3b, replace 
merge 1:m uniq_industry using 产业分类表_示例
keep if _m == 3 
drop _m 
contract class 
save 融合的各产业数量, replace 

和前面一样,这里的 temp3 结果并不是一个对称矩阵,我们也要使用类似的方法把该结果处理成对称矩阵(平衡面板):

*- 融合的各产业数量
use temp3, clear 
gen id = _n 
drop value 
gather industry1 industry2 
keep value
duplicates drop _all, force 
save temp3a, replace 

ren value uniq_industry
save temp3b, replace 
merge 1:m uniq_industry using 产业分类表_示例
keep if _m == 3 
drop _m 
contract class 
save 融合的各产业数量, replace 

*- 处理成对称矩阵
use temp3a, clear
cross using temp3b 
ren value industry1 
ren uniq_industry industry2 
merge 1:1 industry1 industry2 using temp3 
drop _m 
replace value = 0 if mi(value)
save temp3c, replace 

ren industry1 temp 
ren industry2 industry1 
ren temp industry2 
ren value value2 
merge 1:1 industry1 industry2 using temp3c 

egen value3 = rowmax(value value2) 
replace value = value3 
drop value2 _m value3 
replace value = 0 if industry1 == industry2 
save 行业融合数量计算结果, replace 

list, sep(0)

*>     +-----------------------------+
*>     | indust~2   indust~1   value |
*>     |-----------------------------|
*>  1. |       I1         I1       0 |
*>  2. |       I2         I1       2 |
*>  3. |       I3         I1       4 |
*>  4. |       I4         I1       2 |
*>  5. |       I1         I2       2 |
*>  6. |       I2         I2       0 |
*>  7. |       I3         I2       1 |
*>  8. |       I4         I2       1 |
*>  9. |       I1         I3       4 |
*> 10. |       I2         I3       1 |
*> 11. |       I3         I3       0 |
*> 12. |       I4         I3       1 |
*> 13. |       I1         I4       2 |
*> 14. |       I2         I4       1 |
*> 15. |       I3         I4       1 |
*> 16. |       I4         I4       0 |
*>     +-----------------------------+

然后我们就可以根据公式计算数实融合水平了:

use 行业融合数量计算结果, clear 
ren industry1 uniq_industry 
merge m:1 uniq_industry using 产业分类表_示例
keep if _m == 3
drop _m 
ren uniq_industry industry1 
ren class class1 

ren industry2 uniq_industry 
merge m:1 uniq_industry using 产业分类表_示例
keep if _m == 3
drop _m 
ren uniq_industry industry2 
ren class class2 
drop if value == 0 
save temp4, replace 

*- 计算三种融合的数量
collapse (sum) value, by(class1 class2)
save temp5, replace 

use temp4, clear 
ren class1 class 
merge m:1 class using 融合的各产业数量 
drop _m 
ren _freq freq1 
ren class class1 

ren class2 class 
merge m:1 class using 融合的各产业数量 
drop _m 
ren _freq freq2 
ren class class2 

collapse (sum) value (first) freq1 (first) freq2, by(class1 class2)
gen RH = value / (freq1 * freq2)

gen class = "数实融合" if class1 != class2 
replace class = "数数融合" if class1 == "数字产业" & class2 == "数字产业" 
replace class = "实实融合" if class1 == "实体产业" & class2 == "实体产业" 

keep class RH 
duplicates drop _all, force 

list
*>     +---------------+
*>     | RH      class |
*>     |---------------|
*>  1. | .5   实实融合 |
*>  2. |  2   数实融合 |
*>  3. |  1   数数融合 |
*>     +---------------+

这样就计算得到了数实融合水平是 2,数数融合水平是 1,实实融合水平是 0.5。

基于真实数据的计算

数字经济及其核心产业统计分类(2021)

从国家知识产权局的官网上就可以下载到「数字经济及其核心产业统计分类(2021).docx」文件了,使用下面的代码即可提取里面的表格:

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")

haven::read_dta("数字经济及其核心产业统计分类.dta") %>% 
  DT::datatable()

根据论文的建议,我们选取数字经济前四类核心产业作为测算数实融合的数字产业部分:

use 数字经济及其核心产业统计分类.dta, clear 
keep if substr(小类, 1, 2) != "05" & !mi(小类)
drop if mi(国民经济行业代码) 
gen 数字经济产业 = ""
replace 数字经济产业 = "数字产品制造业" if substr(小类, 1, 2) == "01"
replace 数字经济产业 = "数字产品服务业" if substr(小类, 1, 2) == "02"
replace 数字经济产业 = "数字技术应用业" if substr(小类, 1, 2) == "03"
replace 数字经济产业 = "数字要素驱动业" if substr(小类, 1, 2) == "04"
keep 国民经济行业代码 数字经济产业
ren 国民经济行业代码 industry2 
save 数字经济核心产业, replace 


list in 1/10, sep(0)

*>     +---------------------------+
*>     | indust~2     数字经济产业 |
*>     |---------------------------|
*>  1. | 3911       数字产品制造业 |
*>  2. | 3912       数字产品制造业 |
*>  3. | 3913       数字产品制造业 |
*>  4. | 3914       数字产品制造业 |
*>  5. | 3915       数字产品制造业 |
*>  6. | 3919       数字产品制造业 |
*>  7. | 3921       数字产品制造业 |
*>  8. | 3922       数字产品制造业 |
*>  9. | 3940       数字产品制造业 |
*> 10. | 3931       数字产品制造业 |
*>     +---------------------------+

国民经济分类与IPC分类号对照表

为了建立 IPC 分类号和国民经济行业分类的关系,我们还需要处理下「国民经济分类与IPC分类号对照表」,该文件也是来自国家知识产权局:

library(tidyverse)
readxl::read_xlsx("国际专利分类与国民经济行业分类参照关系表(2018).xlsx") %>% 
  set_names("国民经济行业代码""国民经济行业名称",
            "国际专利分类号""国际专利分类号类名") %>% 
  mutate(行业门类代码 = if_else(str_detect(国民经济行业代码, "[A-Z]"), 国民经济行业代码, "")) %>% 
  type_convert() %>% 
  fill(行业门类代码) %>% 
  mutate(国民经济行业代码 = if_else(str_length(国民经济行业代码) == 3 &
                              !str_detect(国民经济行业代码, "^0"), 
                            paste0("0", 国民经济行业代码), 国民经济行业代码)) %>% 
  filter(str_length(国民经济行业代码) == 4 | is.na(国民经济行业代码)) %>% 
  fill(国民经济行业代码, 国民经济行业名称) %>% 
  filter(!is.na(国际专利分类号)) %>% 
  mutate_all(~str_remove_all(.x, "\\r|\\n")) %>% 
  mutate(国民经济行业代码 = paste0(行业门类代码, 国民经济行业代码)) %>% 
  select(-行业门类代码) %>% 
  haven::write_dta("国民经济分类与IPC分类号对照表.dta", label = "数据处理:微信公众号 RStata")

haven::read_dta("国民经济分类与IPC分类号对照表.dta") %>% 
  DT::datatable()

实体产业分类

按照论文的介绍,实体产业可以分为下面四类:

  • 制造业
  • 农业
  • 建筑业及其他工业
  • 服务业
use 国民经济分类与IPC分类号对照表.dta, clear 
gen 实体产业 = ""
gen 行业门类 = substr(国民经济行业代码, 1, 1)
order 行业门类 
replace 实体产业 = "制造业" if 行业门类 == "C"
replace 实体产业 = "农业" if 行业门类 == "A"
replace 实体产业 = "建筑业及其他工业" if inlist(行业门类, "B""D""E")
replace 实体产业 = "服务业" if inlist(行业门类, "I""O")
save 实体产业分类, replace 

不过这个在本次课中用不到。

专利数据中所有的 IPC 号

虽然和国民经济行业代码对照的国际专利分类号有差不多 18000 个,不过并不是每个 IPC 号都在专利数据中出现过。因此我们首先需要统计所有专利数据中互不相同的 IPC 号,然后和这个「国民经济分类与IPC分类号对照表」进行匹配:

专利数据太大了,这里就不再放在附件了。大家重现下面的代码可以从这里下载:https://rstata.duanshu.com/#/brief/course/edef981592a64257aa41e2b6d6d21746

local url = "/Volumes/A10R2copy/A10T/大数据/1985~2022 年专利申请数据(已更新,含授权信息、申请人地址的经纬度及其所处的省市区县信息)/newpatentdata_coord2/"
use "`url'/1985patent_v2_coord.dta"clear 
ren 分类号 IPC 
replace IPC = subinstr(IPC, "//""", .)
replace IPC = subinstr(IPC, "(""", .)
replace IPC = subinstr(IPC, ")""", .)
replace IPC = subinstr(IPC, "=""", .)
replace IPC = subinstr(IPC, ","";", .)
drop if 专利类型 == "外观设计"
drop if !index(IPC, ";")
keep newzlid IPC 
replace IPC = subinstr(IPC, " """, .)

mata:
ipc = st_sdata(., "IPC")
ipc2 = rowshape(ipc, cols(ipc))
ipc3 = invtokens(ipc2, ";")
ipc4 = ustrsplit(ipc3, ";")
ipc5 = colshape(ipc4, 1)
ipc6 = uniqrows(ipc5)
st_matrix("obs", rows(ipc6))
stata("clear")
stata("cap drop uniq_ipc")
st_addvar("strL""uniq_ipc")
stata("set obs `=obs[1,1]'")
st_sstore(., "uniq_ipc", ipc6)
end 

循环所有年份的:

*- 循环所有年份获得所有的 IPC 
cap mkdir "uniq_ipc"
local url = "/Volumes/A10R2copy/A10T/大数据/1985~2022 年专利申请数据(已更新,含授权信息、申请人地址的经纬度及其所处的省市区县信息)/newpatentdata_coord2/"
forval y = 1985/2022 {
  di "`y'"
  qui {
    use "`url'/`y'patent_v2_coord.dta"clear 
    ren 分类号 IPC 
    replace IPC = subinstr(IPC, "//""", .)
    replace IPC = subinstr(IPC, ","";", .)
    replace IPC = subinstr(IPC, "=""", .)
    drop if 专利类型 == "外观设计"
    drop if !index(IPC, ";")
    keep newzlid IPC 
    replace IPC = subinstr(IPC, " """, .)

    mata: ipc = st_sdata(., "IPC")
    mata: ipc2 = rowshape(ipc, cols(ipc))
    mata: ipc3 = invtokens(ipc2, ";")
    mata: ipc4 = ustrsplit(ipc3, ";")
    mata: ipc5 = colshape(ipc4, 1)
    mata: ipc6 = uniqrows(ipc5)
    mata: st_matrix("obs", rows(ipc6))
    mata: stata("clear")
    mata: stata("cap drop uniq_ipc")
    mata: st_addvar("strL""uniq_ipc")
    mata: stata("set obs `=obs[1,1]'")
    mata: st_sstore(., "uniq_ipc", ipc6)
    save uniq_ipc/`y'replace 
  }
}

合并所有的:

use uniq_ipc/1985, clear 
forval y = 1986/2022 {
  append using uniq_ipc/`y'
}
duplicates drop uniq_ipc, force 
replace uniq_ipc = subinstr(uniq_ipc, "(""", .) if ustrregexm(uniq_ipc, "^\(")
replace uniq_ipc = ustrregexs(1) if ustrregexm(uniq_ipc, "(.*)\(")
replace uniq_ipc = subinstr(uniq_ipc, ")""", .)
replace uniq_ipc = ustrregexs(1) if ustrregexm(uniq_ipc, "(.*):")
replace uniq_ipc = subinstr(uniq_ipc, "C07D209/14C07D209""C07D209/14", .)
replace uniq_ipc = subinstr(uniq_ipc, "A61K31/52A61K31""A61K31/52", .)
drop if mi(uniq_ipc)
drop if !ustrregexm(substr(uniq_ipc, 1, 1), "[A-Z]")
save uniq_ipc, replace 

筛选能够和国民经济分类对应上的 IPC 分类号

「国民经济分类与IPC分类号对照表.dta」数据中给出了非常多的分类号和行业小类的对照,不过并不是所有的 IPC 号都在专利数据中出现过,因此我们可以筛选能够匹配上行业小类的:

use 国民经济分类与IPC分类号对照表.dta, clear 
gen dzid = _n 
order dzid 
ren 国际专利分类号 IPC 
replace IPC = subinstr(IPC, "*""", .) 
replace IPC = subinstr(IPC, " """, .) 
gen len = strlen(IPC)
tab len 

*- 分长度保存
cap mkdir "对照表"
forval i = 3/11 {
  preserve 
  keep if len == `i' 
  drop len 
  save 对照表/len`i'replace 
  restore 
}

*- IPC 数据和对照表匹配
use uniq_ipc, clear 
cap mkdir "行业匹配结果"
gen len = strlen(uniq_ipc)
tab len 
gsort -len 
*- 删除 len > 11 的,不值得为个别观测值浪费大量时间处理
drop if len > 11 | len < 3 
forval i = 3/11 {
  preserve 
  keep if len == `i'
  drop len 
  gen IPC = substr(uniq_ipc, 1, `i')
  joinby IPC using 对照表/len`i' 
  save 行业匹配结果/`i'replace 
  restore 


use 行业匹配结果/3, clear 
forval i = 4/11 {
  append using 行业匹配结果/`i'
}
duplicates drop _all, force 
keep uniq_ipc 国民经济行业代码 
save 专利数据与行业小类代码简易对照表, replace 

list in 1/10

*>     +--------------------+
*>     | uniq_ipc   国民~码 |
*>     |--------------------|
*>  1. |     H01L   C3974   |
*>  2. |     H01L   C3563   |
*>  3. |     H01L   C3073   |
*>  4. |     H01L   C3979   |
*>  5. |     H01L   C3562   |
*>     |--------------------|
*>  6. |     H01L   C3973   |
*>  7. |     H01L   C3976   |
*>  8. |     H01L   C3825   |
*>  9. |     H01L   C4028   |
*> 10. |     H01L   C3421   |
*>     +--------------------+

可以看到每个分类号是可能对应多个行业小类的,我们把这些行业小类收集起来:

*- 注意每个 IPC 会对应不同的行业,每个行业也会对应不同的 IPC 分类号
use 专利数据与行业小类代码简易对照表, clear 
recast str11 uniq_ipc
bysort uniq_ipc: gen id = _n 
tostring id, replace 
replace id = "m" + id
spread id 国民经济行业代码
unite m*, gen(国民经济行业代码) sep(";")
drop m*
forval i = 1/30 {
  replace 国民经济行业代码 = subinstr(国民经济行业代码, ";;"";", .)
}
replace 国民经济行业代码 = subinstr(国民经济行业代码, ";"" ", .)
replace 国民经济行业代码 = strtrim(国民经济行业代码)
replace 国民经济行业代码 = subinstr(国民经济行业代码, " "";", .)
save 专利数据与行业小类代码简易对照表2, replace 

也就是大概只有 3000 多个 IPC 分类号是可以对应上行业小类的。

产业数实分类

基于上面的数字经济产业分类和实体产业分类,我们就可以对所有的行业小类进行分类了:

*- 产业数实分类
use 数字经济核心产业.dta, clear 
use 国民经济分类与IPC分类号对照表.dta, clear 
keep 国民经济行业代码 
duplicates drop 国民经济行业代码, force 
gen industry2 = substr(国民经济行业代码, 2, .)
joinby industry2 using 数字经济核心产业.dta, unmatched(master)
drop if mi(国民经济行业代码)
drop _m 
joinby 国民经济行业代码 using 实体产业分类.dta, unmatched(master)
drop industry2 _m 
keep 国民经济行业代码 数字经济产业 实体产业 
gen class = (!mi(数字经济产业)) 

collapse (sumclassby(国民经济行业代码)
gen 类别 = "数字经济产业" if class > 0 
replace 类别 = "实体产业" if class == 0 
drop class 
tab 类别 
save 产业数实分类, replace 

如果某个行业小类同时对应了实体产业和数字产业,归类到数字产业中。

以 2012 年的专利数据为例进行计算

这样我们就已经有了所需的所有数据了。

首先,保留所需的变量:

*- use 2012patent_v2_coord.dta, clear 
*- keep newzlid 公开公告号 专利类型 分类号 
*- ren 分类号 IPC 
*- save 2012patent_small, replace 

去除重复的专利以及删除用不到的外观设计专利:

use 2012patent_small, clear 
*- 去除重复的专利
drop if 专利类型 == "外观设计" 
gen temp = substr(公开公告号, -1, 1)
replace 公开公告号 = subinstr(公开公告号, temp, "", .) if ustrregexm(temp, "[A-Z]")
drop temp 
duplicates drop 公开公告号, force 
drop if !index(IPC, ";")
keep newzlid IPC 
replace IPC = subinstr(IPC, " """, .)
split IPC, parse(;)
drop IPC 
keep newzlid IPC1-IPC10 
save tempdata1, replace 

把没有行业小类对照的都替换成空(这样可以减少下面的计算量):

use tempdata1, clear 
forval i = 1/10 {
  ren IPC`i' uniq_ipc 
  merge m:1 uniq_ipc using 专利数据与行业小类代码简易对照表2 
  drop if _m == 2 
  replace uniq_ipc = "" if _m != 3 
  drop _m 
  ren uniq_ipc IPC`i'
  drop 国民经济行业代码
}
save tempdata1a, replace 

use tempdata1a, clear 
unite IPC*, gen(国际专利分类号) sep(";")
drop IPC*

forval i = 1/30 {
  replace 国际专利分类号 = subinstr(国际专利分类号, ";;"";", .)
}

drop if 国际专利分类号 == ";"
replace 国际专利分类号 = subinstr(国际专利分类号, ";"" ", .)
replace 国际专利分类号 = strtrim(国际专利分类号)
replace 国际专利分类号 = subinstr(国际专利分类号, " "";", .)

drop if !index(国际专利分类号, ";")
ren 国际专利分类号 ipc 
save tempdata2, replace

统计 IPC 共现矩阵:

use tempdata2, clear 
contract ipc 
mata:
    ipc = st_sdata(., "ipc")
    value = st_data(., "_freq"
    fullcombinations = J(0, 3, "")
    for (r = 1; r <= rows(ipc); r++) {
        class_list = colshape(ustrsplit(ipc[r, 1], ";"), 1)
        n_classes = rows(class_list)
        if (n_classes == 2) {
          fullcombinations = fullcombinations \ (class_list[1,1], class_list[2,1], strofreal(value[r,1]))
        }
        if (n_classes > 2) {
          combinations = J(n_classes * n_classes, 3, "")
          row_index = 1
        
          for (i = 1; i <= n_classes; i++) {
              for (j = 1; j <= n_classes; j++) {
                  combinations[row_index, 1] = class_list[i,1]
                  combinations[row_index, 2] = class_list[j,1]
                  combinations[row_index, 3] = strofreal(value[r,1])
                  row_index++
              }
          }
          fullcombinations = fullcombinations \ combinations 
        }
    }

    st_matrix("obs", rows(fullcombinations))
    stata("clear")
    st_addvar("str100""ipc1")
    st_addvar("str100""ipc2")
    st_addvar("str100""value")
    stata("set obs `=obs[1,1]'")
    st_sstore(., ("ipc1""ipc2""value"), fullcombinations)
end

destringreplace 
compress 
save tempdata3, replace 
list in 1/10 

*>     +-------------------------------+
*>     |      ipc1        ipc2   value |
*>     |-------------------------------|
*>  1. |  A01G1/00    A01G1/02       1 |
*>  2. |  A01G1/00    A01G1/04      23 |
*>  3. |  A01G1/00    A01G1/06      28 |
*>  4. |  A01G1/00    A01G1/12       2 |
*>  5. |  A01G1/00   A01G23/00      25 |
*>     |-------------------------------|
*>  6. |  A01G1/00    A01G1/00       2 |
*>  7. |  A01G1/00   A01G23/00       2 |
*>  8. |  A01G1/00   A01G23/04       2 |
*>  9. | A01G23/00    A01G1/00       2 |
*> 10. | A01G23/00   A01G23/00       2 |
*>     +-------------------------------+

汇总后再把这个结果转换成平衡面板(对称矩阵的长面板样式):

use tempdata3, clear 
collapse (sum) value, by(ipc1 ipc2) 
replace value = 0 if ipc1 == ipc2
save tempdata3a, replace 

*- 处理成对称矩阵 
use tempdata3a, clear 
gen id = _n 
drop value 
gather ipc1 ipc2 
keep value 
duplicates drop value, force 
save tempdata3b, replace 

ren value value2 
cross using tempdata3b
ren value ipc1 
ren value2 ipc2 
merge 1:1 ipc1 ipc2 using tempdata3a 
drop _m 
replace value = 0 if mi(value)
save tempdata3c, replace 

ren ipc1 temp 
ren ipc2 ipc1 
ren temp ipc2 
ren value value2 
merge 1:1 ipc1 ipc2 using tempdata3c 
egen value3 = rowmax(value value2) 
replace value = value3 
drop value2 _m value3 
replace value = 0 if ipc1 == ipc2
drop if value == 0 
save IPC融合数量计算结果, replace 

list in 1/10 

*>     +------------------------------+
*>     |     ipc1        ipc2   value |
*>     |------------------------------|
*>  1. | A01G1/00    A01G1/02       1 |
*>  2. | A01G1/00    A01G1/04      23 |
*>  3. | A01G1/00    A01G1/06      28 |
*>  4. | A01G1/00    A01G1/12       2 |
*>  5. | A01G1/00   A01G23/00      30 |
*>     |------------------------------|
*>  6. | A01G1/00   A01G23/02       3 |
*>  7. | A01G1/00   A01G23/04      21 |
*>  8. | A01G1/00   A01G25/16       1 |
*>  9. | A01G1/00    A23L1/08       1 |
*> 10. | A01G1/00    A23L1/10       1 |
*>     +------------------------------+

根据 IPC 和行业小类的对照表就可以把上面的 IPC 号替换成行业小类了:

use IPC融合数量计算结果, clear 
ren ipc1 uniq_ipc
merge m:1 uniq_ipc using 专利数据与行业小类代码简易对照表2.dta
drop if _m == 2 
drop _m 
ren 国民经济行业代码 industry1 
drop uniq_ipc 

ren ipc2 uniq_ipc 
merge m:1 uniq_ipc using 专利数据与行业小类代码简易对照表2.dta
drop if _m == 2 
drop _m 
ren 国民经济行业代码 industry2 
drop uniq_ipc 

order industry*
foreach i of varlist _all {
  cap format `i' %10s 
}
drop if mi(industry1) | mi(industry2) 

drop if industry1 == ";"
replace industry1 = subinstr(industry1, ";"" ", .)
replace industry1 = strtrim(industry1)
replace industry1 = subinstr(industry1, " "";", .)

drop if industry2 == ";"
replace industry2 = subinstr(industry2, ";"" ", .)
replace industry2 = strtrim(industry2)
replace industry2 = subinstr(industry2, " "";", .)

save tempdata4, replace 

再使用 Mata 代码统计行业共现频次:

*- 统计各行业间的合作频次
use tempdata4, clear 
collapse (sum) value, by(industry1 industry2) 
mata:
  mata clear 
  fullcombinations = J(0, 3, "")
  value = st_data(., "value")
  // industry 矩阵
  industry1 = st_sdata(., "industry1")
  industry2 = st_sdata(., "industry2")

  for (z = 1; z <= rows(industry1); z++) {
    a = ustrsplit(industry1[z,1], ";")
    b = ustrsplit(industry2[z,1], ";")
    combinations = J(cols(a) * cols(b), 3, "")
    row_index = 1
    for (i = 1; i <= cols(a); i++) {
      for (j = 1; j <= cols(b); j++) {
        combinations[row_index, 1] = a[1, i]
        combinations[row_index, 2] = b[1, j]
        combinations[row_index, 3] = strofreal(value[z,1]) 
        row_index++
      }
    }
    fullcombinations = fullcombinations \ combinations 
  }
  st_matrix("obs", rows(fullcombinations))
  stata("clear")
  st_addvar("str100""industry1")
  st_addvar("str100""industry2")
  st_addvar("str100""value")
  stata("set obs `=obs[1,1]'")
  st_sstore(., ("industry1""industry2""value"), fullcombinations)
end 
destringreplace 
compress 
collapse (sum) value, by(industry1 industry2)
save tempdata5, replace 

同样,这个结果也并不是平衡面板(对称矩阵),下面还会需要再处理下。不过我们先统计下数字和实体行业的数量:

use tempdata5, clear 
replace value = 0 if industry1 == industry2 
gen id = _n 
drop value 
gather industry1 industry2 
keep value
duplicates drop _all, force 
save tempdata5a, replace 
ren value 国民经济行业代码 
save tempdata5b, replace 
merge 1:m 国民经济行业代码 using 产业数实分类
keep if _m == 3 
drop _m 
contract 类别
ren 类别 class
save 融合的各产业数量, replace 

list

*>     +----------------------+
*>     |        class   _freq |
*>     |----------------------|
*>  1. |      实体产业     296 |
*>  2. |  数字经济产业      26 |
*>     +----------------------+

处理平衡:

use tempdata5a, clear 
cross using tempdata5b 
ren value industry1 
ren 国民经济行业代码 industry2
merge 1:1 industry1 industry2 using tempdata5 
replace value = 0 if mi(value)
drop _m 
replace value = 0 if industry1 == industry2 
save tempdata5c, replace 
ren industry1 temp 
ren industry2 industry1 
ren temp industry2 
ren value value2 
merge 1:1 industry1 industry2 using tempdata5c 
egen value3 = rowmax(value value2) 
replace value = value3 
drop value2 _m value3 
replace value = 0 if industry1 == industry2 

匹配上行业类别再分类计算总数量:

ren industry1 国民经济行业代码 
recast str5 国民经济行业代码
merge m:1 国民经济行业代码 using 产业数实分类
keep if _m == 3
drop _m 
ren 国民经济行业代码 industry1 
ren 类别 class1

ren industry2 国民经济行业代码 
recast str5 国民经济行业代码
merge m:1 国民经济行业代码 using 产业数实分类
keep if _m == 3
drop _m 
ren 国民经济行业代码 industry2 
ren 类别 class2 
drop if value == 0 
collapse (sum) value , by(class1 class2)
save tempdata6, replace 

最后就可以计算数实、数数和实实融合水平了:

use tempdata6, clear 
ren class1 class 
merge m:1 class using 融合的各产业数量 
drop _m 
ren _freq freq1 
ren class class1 

ren class2 class 
merge m:1 class using 融合的各产业数量 
drop _m 
ren _freq freq2 
ren class class2 

collapse (sum) value (first) freq1 (first) freq2, by(class1 class2)
gen RH = value / (freq1 * freq2)

gen class = "数实融合" if class1 != class2 
replace class = "数数融合" if class1 == "数字经济产业" & class2 == "数字经济产业" 
replace class = "实实融合" if class1 == "实体产业" & class2 == "实体产业" 

keep class RH 
duplicates drop _all, force 

list

*>     +---------------------+
*>     |       RH      class |
*>     |---------------------|
*>  1. | 18.74731   实实融合  |
*>  2. | 1.294958   数实融合  |
*>  3. | 52.50888   数数融合  |
*>     +---------------------+

不过计算结果和原论文中的有些差异,令人费解。不过考虑到数字经济产业并不多,所以数实融合的专利不会很多,因此数实融合水平应该也不会很高。这个结果应该是合理的。

如果想分城市,只需要循环使用各城市的专利数据计算即可;如果想要分类别(农业、建筑业、制造业、建筑业及其他工业),只需要最后在分组计算的时候使用这个类别变量即可。

如何参加课程?

购买 RStata 名师讲堂会员都可以参加这个课程啦!

详情可阅读这篇推文:数据处理、图表绘制、效率分析与计量经济学如何学习~,更多关于 RStata 培训班的信息可添加微信号 r_stata 咨询(上图中有二维码)。

会员购买:从首页的会员卡专区即可查看和购买会员卡。

https://rstata.duanshu.com/#/card/list/

课程主页(点击文末的阅读原文即可跳转):

https://rstata.duanshu.com/#/brief/course/e4f7e30bd24f4b67a637b702b08d2d6b


RStata
一起学习 R 语言和 Stata 吧!
 最新文章