python 全局莫兰指数和局部莫兰指数

import esda
import pandas as pd
import geopandas as gpd
from geopandas import GeoDataFrame
import libpysal as lps
import numpy as np
import matplotlib.pyplot as plt
from shapely.geometry import Point
import contextily as ctx
from pylab import figure, scatter, show
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline

关于geopandas和contextily库的安装,参考我的另一篇博客https://www.jianshu.com/p/a1496e316bb4

读取数据

一个是地图信息,一个是需要研究的指标。

# 除中华人民共和国.shp外其余三个文件必须也在,只有一个则读取出错
# 中华人民共和国.dbf
# 中华人民共和国.prj
# 中华人民共和国.shx
gdf_data = gpd.read_file('data/中华人民共和国.shp',encoding='utf_8_sig')
feature_df = pd.read_excel('data/清洁低碳.xlsx')

构建邻接矩阵

wq = lps.weights.Queen.from_dataframe(gdf_data) #使用Quuen式邻接矩阵
wq.transform = 'r' #标准化矩阵
# 两个省没有直接相邻的省(34行数据不清楚是什么,下载地图shp文件中自带的)
print(gdf_data.loc[[20,31],'name'])
'''
('WARNING: ', 20, ' is an island (no neighbors)')
('WARNING: ', 31, ' is an island (no neighbors)')
('WARNING: ', 34, ' is an island (no neighbors)')
20    海南省
31    台湾省
Name: name, dtype: object
'''

centroids = gdf_data.geometry.centroid # 计算多边形几何中心
# 本图将邻接矩阵覆盖在整个地图上,如果只需要邻接矩阵,删除ax = gdf_data.plot(figsize=(10, 10),cmap="Blues")
ax = gdf_data.plot(figsize=(10, 10),cmap="Blues")
plt.plot(centroids.x, centroids.y, '.')
for k, neighs in wq.neighbors.items():
    origin = centroids[k]
    for neigh in neighs:
        segment = centroids[[k,neigh]]
        plt.plot(segment.x, segment.y, '-')
plt.title('Queen Neighbor Graph')
plt.axis('off')
plt.show()
plt.savefig("save/{}.jpg".format('wq'),dpi=300) # 图片模糊问题,需要指定图片的dpi大小
局部中国地图.jpg

批量计算2010-2020年的全局莫兰指数

合并数据,自动去掉不研究的数据(不带指标的省份)

# 实际数据只研究30个省份,不包含香港澳门,台湾和西藏
gdf_drop = gdf_data.merge(feature_df,left_on='name',right_on='地区')
wq = lps.weights.Queen.from_dataframe(gdf_drop)
wq.transform = 'r' # 标准化矩阵
centroids = gdf_drop.geometry.centroid # 计算多边形几何中心
wr = lps.weights.Rook.from_dataframe(gdf_drop)# 使用Rook式邻接矩阵

Moran_I_list = []
random_Z_list = []
random_Zp_list = []
norm_Z_list = []
norm_Zp_list = []

for i in range(12, 23): # 按照列名位置
    y_name = gdf_drop.columns[i]
    y = gdf_drop[y_name]
    mi = esda.moran.Moran(y, wq)
    
    Moran_I_list.append(mi.I)
    random_Z_list.append(mi.z_rand)
    random_Zp_list.append(mi.p_rand)
    norm_Z_list.append(mi.z_norm)
    norm_Zp_list.append(mi.p_norm)

Moran_I_df = pd.DataFrame()
Moran_I_df['year'], Moran_I_df['Moran_I'], Moran_I_df['random_Z'], Moran_I_df['random_p'], Moran_I_df['norm_Z'], Moran_I_df['norm_p'] = \
(range(2010, 2021), Moran_I_list, random_Z_list, random_Zp_list, norm_Z_list, norm_Zp_list)

print(Moran_I_df)
'''
    year   Moran_I  random_Z  random_p    norm_Z    norm_p
0   2010  0.4xxxxx  4.xxxxx   0.0xxxxx    4.1xxxxx   0.0xxxxx
1   2011  0.4xxxxx  3.xxxxx   0.0xxxxx    3.7xxxxx   0.0xxxxx
2   2012  0.4xxxxx  3.xxxxx   0.0xxxxx    3.8xxxxx   0.0xxxxx
3   2013  0.4xxxxx  3.xxxxx   0.0xxxxx    3.9xxxxx   0.0xxxxx
4   2014  0.4xxxxx  4.xxxxx   0.0xxxxx    4.0xxxxx   0.0xxxxx
(省略)
'''

以2020年为例展示计算的莫兰指数和检验结果

y = gdf_drop["2020y"]
mi = esda.moran.Moran(y, wq)

print("Moran's I 值为:",mi.I)
print("随机分布假设下Z检验值为:",mi.z_rand)
print("随机分布假设下Z检验的P值为:",mi.p_rand)
print("正态分布假设下Z检验值为:",mi.z_norm)
print("正态分布假设下Z检验的P值为:",mi.p_norm)
'''
Moran's I 值为: 0.4542425813757728
随机分布假设下Z检验值为: 4.xxxxxx
随机分布假设下Z检验的P值为: 6.xxxxxxe-05
正态分布假设下Z检验值为: 4.xxxxxx
正态分布假设下Z检验的P值为: 5.xxxxxx-05
'''

绘制2020年的莫兰散点图

from splot.esda import plot_moran
fig, ax = plot_moran(mi, zstandard=True, figsize=(11,5),aspect_equal=False)
fig.show()
fig.savefig("save/{}.jpg".format('清洁低碳全局莫兰散点图'),dpi=300) # 图片模糊问题,需要指定图片的dpi大小
清洁低碳全局莫兰散点图.jpg

2020年全局莫兰指数检验通过,继续做局部莫兰指数(全局不通过,不用做局部)

from splot.esda import moran_scatterplot
from esda.moran import Moran_Local
from splot.esda import lisa_cluster
from splot.esda import plot_local_autocorrelation

y = gdf_drop['2020y'].values
w = lps.weights.distance.Kernel.from_dataframe(gdf_drop, fixed=False, k=15)
w.transform = 'r'
moran_loc = Moran_Local(y, w)

# 局部莫兰指数
loc_moran_df = pd.DataFrame({'name':gdf_drop.name, 'loc_moran':moran_loc.Is}) # moran_loc.Is是各省的局部莫兰指数
print(loc_moran_df)
'''
        name  loc_moran
0        北京市  -0.033960
1        天津市   0.319125
2        河北省  -0.086364
3        山西省   0.000686
4     内蒙古自治区   0.068562
5        辽宁省  -0.063257
6        吉林省   0.002306
7       黑龙江省  -0.012012
8        上海市   0.001538
9        江苏省   0.025877
10       浙江省   0.307162
(省略)
'''

局部莫兰散点图

fig, ax = moran_scatterplot(moran_loc, p=0.1,aspect_equal=True)
#ax.set_xlabel('FSTGDPRATE')
#ax.set_ylabel('Spatial Lag of FSTGDPRATE')
#plt.show()
fig.savefig("save/{}.jpg".format('清洁低碳局部莫兰散点图'),dpi=300) # 图片模糊问题,需要指定图片的dpi大小
清洁低碳局部莫兰散点图.jpg

空间分布图(不展示组合图)

强调:没有计算西藏地区,所以中国大陆地图中缺失西藏地区

fig, ax = lisa_cluster(moran_loc, gdf_drop, p=0.1, figsize = (9,9))
fig.savefig("save/{}.jpg".format('清洁低碳聚集区的空间分布图'),dpi=300) # 图片模糊问题,需要指定图片的dpi大小

#绘制组合图(不展示组合图)
#fig, ax = plot_local_autocorrelation(moran_loc, gdf_drop, '2020y',p=0.1,figsize = (27,6))
#fig.savefig("save/{}.jpg".format('清洁低碳组合图'),dpi=300) # 图片模糊问题,需要指定图片的dpi大小
能源高质量发展聚集区的空间分布图.jpg

参考:
https://www.yisu.com/zixun/503529.html
https://www.yisu.com/zixun/504927.html


实操问题

做完全局莫兰指数后,计算局部莫兰指数的函数 Moran_Local 一直出错,其中提到 numba 库的问题。我查询报错,发现有个提升 numba 版本的说法,然后我升级到最新版本。随后直接导致 esda 库和 libpysal 库导入失败,导致全局莫兰指数部分无法运行。随后我卸载了numba,esda 和 libpysal,再次安装 numba,esda 和 libpysal,依然无法导入 esda 和 libpysal。尝试多种方法后,我再一次卸载了 numba,esda 和 libpysal,然后只安装 esda 库,神奇的是我可以导入esda,甚至可以直接导入 libpysal,连之前出错的 Moran_Local 函数也可以运行了。我推测是Moran_Local 依赖的 numba 库版本和我的 numba 库版本不一致,在我将 numba 库版本升级成最新版时,又与 esda 和 libpysal 不匹配。最后我删除 numba 后,只安装最新的 esda,会自己下载合适的 numba,然后就可以运行 Moran_Local 函数(esda.moran.Moran_Local)。
此处展示我的环境:

  • Python 3.6.5
  • numba 0.38.0
  • esda 2.4.1
  • libpysal 4.5.0
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容