2018年12月1日,孙慧老师在新疆经济学会2018年年会上做的报告《中国多民族地区融入一带一路》着实惊艳了一把,用网络图来形象的展示了全球价值链很直观啊!一图胜千言,果然不假。该报告数据来源: “一带一路”沿线国家与中国的双边贸易数据来自联合国商贸易统计数据库,主要使用双边货物商品贸易的统计数据。虽然用货物商品贸易数据来表征全球价值链有待商榷,事实上研究全球价值链普遍运用的数据是wiot投入产出表,但不可否认的是这份报告思路很新颖。下面我将做一些尝试重现该份报告的网络图。

无向网路图

1
2
3
4
library(igraph)
set.seed(1234)
gu = graph(c(1,2, 2,3, 2,4, 1,4, 5,5, 3,6), directed = FALSE)
print(gu)
1
2
3
## IGRAPH 3883eda U--- 6 6 -- 
## + edges from 3883eda:
## [1] 1--2 2--3 2--4 1--4 5--5 3--6
1
plot(gu)

有向网络图

1
2
3
set.seed(1234)
gd = graph(c(1,2, 2,3, 2,4, 1,4, 5,5, 3,6), directed = TRUE) # 默认有向,参数可省略。
print(gd)
1
2
3
## IGRAPH 38927bc D--- 6 6 -- 
## + edges from 38927bc:
## [1] 1->2 2->3 2->4 1->4 5->5 3->6
1
plot(gd)

以上两图基本反映了网络图的基本原理,但是没有考虑到他们之间的权重,试想一下,如果1和2之间的贸易额是3亿,2和3之间贸易额是2亿,剩余的2和4, 1和4, 3和6之间贸易额分别是1亿,5和5之间不可能有贸易额,那么该如何作图呢?一个朴素的思想是让1,2出现3次,2,3出现2次,2,4, 1,4, 3,6分别出现1次,5,5出现0次(不出现),下面我们验证这个思路是否可行?

加权有向网络图尝试

1
2
3
4
5
6
7
8
9
set.seed(1234)
gd_w = graph(
  c(1,2, 1,2, 1,2,
    2,3, 2,3,
    2,4, 
    1,4,  
    3,6)
  )
print(gd_w)
1
2
3
## IGRAPH 389e1ce D--- 6 8 -- 
## + edges from 389e1ce:
## [1] 1->2 1->2 1->2 2->3 2->3 2->4 1->4 3->6
1
plot(gd_w)

呵呵,确实可行!!!很明显国家(地区)2在整个网络中处于核心地位。但是这种画法在实践中需要对原始数据根据贸易额进行加工,十分不方便。

通过参数设置权重

1
2
3
4
5
6
set.seed(1234)
d = data.frame(p1 = c(1, 2, 2, 1, 3),
               p2 = c(2, 3, 4, 4, 6),
               wt = c(3, 2, 1, 1, 1))
g = graph.data.frame(d, directed = TRUE)  # 转换数据结构;设置为有向图。
print(g)  # 这里g的数据结构和gu、gd以及gd_w是一样的
1
2
3
4
## IGRAPH 38a9746 DN-- 5 5 -- 
## + attr: name (v/c), wt (e/n)
## + edges from 38a9746 (vertex names):
## [1] 1->2 2->3 2->4 1->4 3->6
1
plot(g, edge.width=E(g)$wt) # layout参数可选

加入权重参数wt的好处是,我们不需要对原数据进行改造,十分方便。图中连线粗细程度反映权重大小。我们只需要保证原数据的数据结构如下即可:

1
2
3
4
5
data = data.frame(
  `出口国` = c("国家1", "国家2", "国家2", "国家1", "国家3"),
  `进口国` = c("国家2", "国家3", "国家4", "国家4", "国家6"),
  `交易额` = c(3, 2, 1, 1, 1))  # 权重
print(data)
1
2
3
4
5
6
##   出口国 进口国 交易额
## 1  国家1  国家2      3
## 2  国家2  国家3      2
## 3  国家2  国家4      1
## 4  国家1  国家4      1
## 5  国家3  国家6      1

利用真实商品和贸易数据生成网络图

载入需要的R包和数据

1
2
3
4
library(openxlsx)
library(tidyverse)
library(igraph)
df = read.xlsx("~/mydata/trade2017.xlsx")  # 数据来源:联合国商品贸易统计数据库

根据原数据生成网络图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
set.seed(1234) # 设置随机数种子,方便可重复性研究。
df %>%
  select(Trade.Flow, Reporter, Partner, `Trade.Value.(US$)`) %>%
  filter(Trade.Flow == "Export") %>%  # 此处只选择出口数据,当然也可只选择进口数据。
  rename(
    p1 = Reporter,
    p2 = Partner,
    value = `Trade.Value.(US$)`
         ) %>%
  select(p1, p2, value)  %>%
  graph.data.frame(directed = TRUE) %>%
  plot(edge.width=E(.)$value/10000000000,
       vertex.size = 3,
       vertex.color = "green",
       vertex.label.dist = 0.6,
       edge.arrow.size = 0.1)

注:此处只选择出口数据是因为a国出口到b国,相当于b国从a国进口,因此只需要保留进口或者出口即可。

去掉出口额小于一定金额的记录

上图虽然信息比较完备,但是由于线条比较密集,所以不利于发现关键信息,因此在筛选出出口额的情况下,考虑删除出口额中小于一定金额的记录(行)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
set.seed(1234)
df %>%
  select(Trade.Flow, Reporter, Partner, `Trade.Value.(US$)`) %>%
  filter(Trade.Flow == "Export") %>%
  rename(
    p1 = Reporter,
    p2 = Partner,
    value = `Trade.Value.(US$)`
  ) %>%
  select(p1, p2, value)  %>%
  filter(value>=500000000) %>%   # 此处选择5亿美元的记录,可灵活调整。
  graph.data.frame(directed = TRUE) %>%
  plot(edge.width=E(.)$value/10000000000,
       vertex.size = 3,
       vertex.color = "green",
       vertex.label.dist = 0.6,
       edge.arrow.size = 0.1)