哪个省能称为“九省通衢”?

扑上有位网友发起了一个很有意思的话题,《湖北是唯一一个到各省区最多只要跨过两个省的省份吗?》这在地理里是个多阶空间邻接矩阵的问题。我觉得这个问题可以作为学习R语言中spdep包的入门吧。顺手解决了一下。中国地图的矢量数据是我从高德上抓取的。先画一个中国地图

library(pacman)
p_load(tidyverse,sf,spdep,tmap)
tm_shape(china_province)+tm_polygons()

哪个省能称为“九省通衢”?
用的包主要是以上这么几个。画图的话也可以用ggplot2
所谓空间邻接矩阵,也就是记录地理实体之间空间邻接关系的矩阵。比如江苏与安徽有着共同的省界,那就记录为1,这种直接相邻的1阶空间相邻。而江苏与湖北之间隔了一个安徽,这就是2阶空间相邻了。(广义上说,这一类矩阵应该叫空间距离矩阵。邻接关系可以看做是拓扑学意义上的距离吧(好像是)。而构建空间距离矩阵是开展空降计量经济学等空间分析的基础。)下面回到问题本身。我们如果用空间邻接关系的语言来重新描述一下这个问题,那就是湖北是中国唯一的其1+2+3阶空间邻接矩阵就包含了中国所有省份的省份吗?果然就不说人话了,哈哈。
下面,我们首先构建所有省份的1阶空间邻接矩阵。

china_nb=poly2nb(as(china_province,'Spatial'),queen=F,
                 row.names = china_province$name)

poly2nb我感觉是spdep这个包中最基础的函数了,我比较习惯使用sf对象,而spdep这些包都有些年头了,其空间对象基本都是围绕sp包来构建的,所以首先要进行对象的转换。queen这个参数是用来设定判别两个多边形是否空间相邻的方式。一般来说有三种,都是按照国际象棋上棋子的走法来命名的。分别有bishop(共顶点),rook(共边),queen(共边或共点)。
poly2nb这个函数的结果是一个nb类型的对象,这是这个包专用的一个对象。实质就是把空间邻接矩阵按行降解了,不以0\1来记录空间邻接关系,而是把与行多边形邻接的多边形的编号记录了下来。长这个样子
哪个省能称为“九省通衢”?

这样的形式相对矩阵形式看起来更直观一些,但在解决我们这个问题时并不好用,因为我需要进一步把1-2阶空间邻接矩阵的信息存储在一个矩阵中,而这个形式显然拓展性是不好的。在R中针对不规则list对象的操作还是有些麻烦的,后面进行是否包含所有省份的验证时也不好操作,所以我们还是要把它转换成矩阵形式。在此之前,有个问题是需要注意的。那就是海南和台湾两个省与大陆是通过海洋相连的,反映到空间邻接矩阵中就是这两个省是没有邻居的。那么也就不会有更高阶的邻接关系。那么如果不做人为限定,原题目就是无法解决的。我这里人为限定海南和台湾分别与其空间距离上最为接近的广东和福建相邻。一定要注意对称性,有联系的省份之间都要赋值

china_nb[[17]]=(1 %>% as.integer) 
china_nb[[26]]=(15 %>% as.integer)
china_nb[[1]]=c(17,china_nb[[1]]) %>% as.integer
china_nb[[15]]=c(26,china_nb[[15]]) %>% as.integer

这里的数字全是我原数据中各省份排列的顺序。注意的是nb对象中的值只能是整数类型,而R语言默认是numeric,这里还要先进行类型转换。
这样全中国所有的省份都有1阶邻居了,我们可以用一个函数一步得到多个高阶邻接矩阵。

nb_lag=nblag(china_nb,maxlag = 3)

为什么说poly2nb这个函数基础呢?因为spdep包中很多函数接收的对象就是nb类型的。maxlag这个参数用来限定高阶邻接矩阵的阶数,设定为2就生成连个list对象。两个list对象都是nb类型。
我们要分别展开为矩阵。

nb_m1=nb2mat(nb_lag[[1]],style='B')
nb_m2=nb2mat(nb_lag[[2]],style='B')
nb_m3=nb2mat(nb_lag[[3]],style='B')
#style参数用来限定展开矩阵的类型,详     
                                                                     情参见帮助文档

哪个省能称为“九省通衢”?
展开后的矩阵是这样的。按行相加(nb_m1 %>% rowSums),就可以知道每个省有多少1阶邻居了。
一阶时这样。
哪个省能称为“九省通衢”?
陕西作为中国的大地原点所在的省份拥有8个邻居,而作为祖国边境省份的内蒙古也同样拥有8个邻居恐怕也是大家没有想到的吧。超长的东西跨度使得内蒙古成为包括了祖国东中西部的省份。湖北的优势则并不突出。
把1阶和2阶矩阵相加,就可以得到2阶内的情况了。我们直接来看看3阶的情况(2阶相加的结果是没有能联通全国的省份。)

(nb_m1+nb_m2+nb_m3) %>% rowSums

哪个省能称为“九省通衢”?湖北果然独占鳌头,下面我们来看看湖北是怎么一步步联系其全国的。

tm_shape(china_province)+tm_borders()+
         tm_shape(china_province[6,])+tm_polygons(col='red')+
         tm_shape(china_province[hb_1,])+tm_polygons(col='yellow')+
         tm_shape(china_province[hb_2,])+tm_polygons(col='blue')+ 
         tm_shape(china_province[hb_3,])+tm_polygons(col='green')

哪个省能称为“九省通衢”?