ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

空间计量入门实战:GeoDa软件与莫兰指数案例详解

空间计量入门实战:GeoDa软件与莫兰指数案例详解

简介:学习空间计量学与GeoDa实操,可以借助这套案例数据包。资源面向空间数据分析初学者、地理信息专业学生及科研人员,覆盖空间权重矩阵构建、全局与局部空间自相关检验、空间回归模型(SLM/SEM)以及地理加权回归(GWR)等核心方法,并提供配套Shapefile空间数据,方便零基础用户从数据预处理、探索性分析到模型解读逐步演练。压缩包共17个文件,以shp、dbf、shx空间数据格式为主,附带sbn/sbx空间索引、html格式案例说明以及pdf变量信息文档,整体仅1.13MB,轻量易得。包内包含多个案例数据集,涵盖不同区域尺度的典型分析场景,读者可结合HTML与PDF说明理解数据背景与变量含义,在GeoDa中完成地图可视化、空间权重设置、Moran's I计算及回归建模等完整流程。目前已有437人学习下载,适合希望快速上手空间统计方法并产出实证分析的入门者。

1. 空间计量学入门与GeoDa软件应用案例数据.zip:先想清楚要拿它做什么

如果你是第一次接触空间计量学,最容易被卡住的地方往往不是统计学本身,而是「数据长什么样、软件怎么点、结果怎么读」这三件事叠在一起时的混乱。GeoDa 是一款免费开源的桌面空间数据分析软件,配合一份组织好的案例数据压缩包,可以让你在几个小时内把空间权重、莫兰指数、空间回归这一整条主线跑通。这个 zip 的价值不在于里面的文件有多少,而在于它是你从概念到输出结果的第一个可复现路径。

我见过不少人的入门方式是把示例数据直接拖进软件,然后对着散点图发愣:不知道权重矩阵是什么时候生成的,也不知道 LISA 图上那几种颜色各代表什么意思。这个压缩包的正确用法,是把它当成一套「可以反复折腾的练习场」——先按顺序跑通标准流程,再故意改坏几个参数,看结果怎么变,这才是它比教科书公式更有用的地方。适合读这篇文章的人有两类:一类是论文需要做空间计量的学生,另一类是第一次拿到面状数据、想判断现象是否存在空间集聚的研究人员。

2. 空间权重矩阵:用 zip 里的 shp 文件生成第一个 Queen 权重

2.1 为什么空间权重矩阵必须先于一切分析

空间计量学跟普通回归的根本差别,在于它显式承认「邻近的事物互相影响」。这个影响怎么进入模型,靠的就是空间权重矩阵 W——一个 n×n 的矩阵,每个元素表示区域 i 和区域 j 之间的空间关系。没有这个矩阵,后面所有空间统计量都无从谈起。所以拿到 zip 解压后的数据,第一件事不是做图,而是先看清这份数据是面状(多边形)还是点状,再决定用哪种权重规则。

GeoDa 里最常见的两种规则是邻接关系和距离关系。邻接关系又分 Rook(共边才算邻居)和 Queen(共边或共顶点都算邻居)。对于入门案例,我一般推荐先用 Queen,理由很实际:许多行政区划图存在顶点恰好相交但边界不相邻的情况,比如一个县城和另一个县城在对角处碰了一下,Queen 会把它们算作邻居,Rook 不会。这种细微差别在结果上可能改变莫兰指数的显著性判断。距离权重则适合点状数据或者区域面积差异过大的情况,但需要你决定阈值距离,这个参数往往带有一定的玄学成分,入门阶段先不碰。

2.2 在 GeoDa 里从 shp 生成 Queen 权重的最小操作

假设你已经把 zip 解压,拿到一个至少包含 .shp、.dbf、.shx 三种文件的文件夹。打开 GeoDa,按下面几步操作:

  1. File → Open,文件类型选 ESRI Shapefile,选中你的 .shp 文件。
  2. 地图窗口出现后,点菜单栏的 Tools → Weights Manager。
  3. 在弹出的窗口里点 Create,Weights Type 选 Queen,ID Variable 选一个每行都不重复的字段(通常是 FID 或 ID)。
  4. 点击 Create 后,GeoDa 会生成一个 .gal 文件,默认保存路径和 shp 在同目录。

这里有个关键点:ID Variable 不能有缺失值,也不能有重复。如果你选的字段里出现了两个「0」,权重文件会生成成功,但后续计算时部分样本会莫名从模型里消失。为了验证这一步是否正确,我习惯用 Python 做一个交叉检查,用同一份数据生成权重,跟 GeoDa 的 .gal 文件做比对。下面这段代码可以在 Jupyter 里直接跑:

import geopandas as gpd from libpysal.weights import Queen # 读取解压后的 shp 文件 gdf = gpd.read_file("case_study/study_area.shp") # 生成 Queen 权重,注意 geoda 默认不含空间岛(无邻居的区域) w = Queen.from_dataframe(gdf, use_index=False) # 检查是否有孤立区域(邻居数为 0) no_neigh = w.islands print("孤岛区域索引:", no_neigh if len(no_neigh) else "无") # 把权重保存为 gal 格式,方便和 GeoDa 的结果对比 w.to_file("case_study/study_area_queen.gal")

这段代码的作用有三个:第一,用 libpysal 重新生成一份 Queen 权重,和 GeoDa 生成的 .gal 文件做对比;第二,检查是否存在没有邻居的区域,这类区域在后续莫兰指数计算中会被默认剔除;第三,给权重文件一个独立备份,方便你在 GeoDa 里重新加载。参数上需要注意 use_index=False 表示用数据框的行号作为观测单位,如果你有真实的行政编码字段,应该把这个字段设为索引再生成,否则权重文件的 ID 顺序可能和你的业务数据对不上。

2.3 压缩包内文件缺失时的识别方法

一份标准的 shp 数据由多个文件组成,除了 .shp 主文件,还有 .dbf(属性表)、.shx(索引)、.prj(坐标系)。入门 zip 包里最常被忽略的是 .prj 文件——它只有几百字节,却记录了坐标系信息。没有它的后果是 GeoDa 能画出地图,但所有面积、距离计算都是错的,因为软件不知道这些坐标的单位是米还是度。如果你解压后没看到 .prj,可以用 QGIS 或 Python 手动补一个投影定义,不要直接开始分析。另外提醒一下,从中文网站下载的案例 zip 有时会用 GBK 编码的 .dbf 字段名,GeoDa 界面里可能显示乱码,这种情况先把字段名改成英文再继续。

3. 空间自相关:用案例数据跑通莫兰指数并读懂四象限图

3.1 全局莫兰指数的直觉与零假设

莫兰指数(Moran's I)是判断空间自相关最常用的统计量。它的直觉非常简单:如果高值区域旁边也是高值,低值旁边也是低值,那这个变量就存在正向的空间集聚,莫兰指数为正;如果高值旁边是低值,像棋盘一样交错,莫兰指数为负。这个指数本身并不难计算,真正容易翻车的是对 p 值和 z 值的解读。GeoDa 默认做的是置换检验(permutation test),它会随机打乱每个区域上的取值,然后观察你实际算出来的莫兰指数落在随机分布的什么位置。

零假设是「变量在空间上完全随机分布」。如果你跑出来的 p 值小于 0.05,说明实际数据不太可能是随机排列的结果,拒绝零假设,认为存在显著的空间自相关。要注意的是,莫兰指数是一个全局指标,它只能告诉你整体上有没有集聚,不能告诉你具体集聚在哪里。更麻烦的是,如果数据里存在极端值,全局莫兰指数会被它牵着走,这时候需要配合局部指标一起看。

3.2 单变量莫兰指数的完整操作流程

在 GeoDa 里,加载 shp 文件之后,点 Space → Univariate Moran's I,选择一个数值型变量,点击 Run。软件会弹出一个散点图窗口,横轴是变量的标准化值,纵轴是空间滞后(邻居的平均值)。同时下方会显示 Moran's I 的数值、p 值和 z 值。这里最常被误解的一点是:散点图里那条回归线的斜率就是莫兰指数本身,而不是「相关性」的替代品。

为了避免只依赖 GeoDa 的界面输出,建议同步用 Python 算一遍,这样你可以确认软件在计算时有没有因为权重矩阵的问题剔除了一些样本。下面是我常用的验证代码:

import geopandas as gpd from libpysal.weights import Queen from esda.moran import Moran gdf = gpd.read_file("case_study/study_area.shp") w = Queen.from_dataframe(gdf, use_index=False) w.transform = "r" # 行标准化,每个邻居的权重按邻居数均分 # 选择要分析的变量,注意 GeoDa 默认会把变量标准化 y = gdf["crime_rate"].values mi = Moran(y, w, permutations=999) print(f"Moran's I: {mi.I:.4f}") print(f"p-value: {mi.p_sim:.4f}") print(f"z-score: {mi.z_sim:.4f}")

这段代码里的 w.transform = "r" 是权重矩阵的行标准化,GeoDa 默认也采用这种方式。行标准化的含义是:一个区域若有 5 个邻居,每个邻居权重为 0.2;若有 2 个邻居,每个邻居权重为 0.5。这样可以避免邻居多的区域在空间滞后计算中天然获得更大权重。permutations 参数设成 999 是经验值,置换次数越多 p 值越稳定,但计算时间也越长,999 是学术论文常用的最低标准,你可以按需调到 9999。

3.3 LISA 聚类图的读法与局部莫兰指数的坑

局部莫兰指数(LISA)把全局指标分解到每个区域,GeoDa 里对应操作是 Space → Univariate Local Moran's I。运行后软件会生成一张聚类图,通常用四种颜色表示:红色是高高集聚(High-High),蓝色是低低集聚(Low-Low),浅红表示高低异常(High-Low),浅蓝表示低高异常(Low-High),白色表示不显著。

读这张图时有一个特别大的坑:LISA 图上的颜色只基于局部莫兰指数及其显著性,但局部莫兰指数在样本量小的时候检验功效很低。如果你只有三四十个区域,很容易出现「看起来红一块蓝一块,但几乎没有区域达到 0.05 显著性水平」的情况。这不是你的数据坏了,也不是软件坏了,而是局部检验本身在小区本下的特性。遇到这种情况,我一般会把显著性水平放宽到 0.1 看一看模式,但论文里绝不会这么写。

4. 空间回归模型:先做 LM 检验再动手,别一上来就跑 SLM

4.1 OLS 在空间数据上为什么可能失守

很多人在跑完莫兰指数之后,就直接跳到空间回归模型,这是不对的。你需要先做一个经典的最小二乘回归(OLS),然后检查它的残差是否存在空间自相关。如果残差有空间自相关,说明你遗漏了空间结构,此时 OLS 的估计虽然仍然无偏,但标准误失效,t 值和 p 值都不可信。更严重的是,如果真实的数据生成过程是空间滞后(y 受邻居 y 的影响),你却用 OLS 估计,所得系数会同时存在偏误和非一致性,这在计量上是个硬伤。

验证残差空间自相关的做法是:用 OLS 跑完模型,把残差保存下来,对残差再做一次莫兰指数检验。在 GeoDa 的回归窗口里,这个检验是内嵌的,不需要你手动保存残差。要注意搜索路径:Space → Regression → Classic,选择因变量和自变量,运行后看回归结果窗口底部的诊断表。如果残差莫兰指数的 p 值小于 0.05,你就需要认真考虑空间模型了。

4.2 Lagrange Multiplier 检验:选 SLM 还是 SEM 的判断依据

面对残差空间自相关,最常见的两个模型是空间滞后模型(SLM,Spatial Lag Model)和空间误差模型(SEM,Spatial Error Model)。前者认为空间依赖来自因变量本身,比如一个地区的犯罪率会直接影响邻近地区的犯罪率;后者认为空间依赖来自遗漏的扰动项,比如两个相邻地区共享了某些你没观测到的环境因素。在经济学的理论框架里,这两个模型对应完全不同的行为假设,选错模型会得到完全不同的政策含义。

判断依据是 Lagrange Multiplier 检验,在 GeoDa 的 OLS 回归结果中会直接给出 LM-Lag 和 LM-Error 两项统计量及对应的 p 值。规则比较简单:

LM-Lag 显著LM-Error 显著推荐做法
是否空间滞后模型 SLM
否是空间误差模型 SEM
是是跑稳健 LM 检验,看哪个更显著
否否维持 OLS,不必强上空间模型

最后一行特别重要。我见过很多案例,残差莫兰指数显著,但 LM-Lag 和 LM-Error 都不显著,这时强行套空间模型只会得到一个系数全不显著的模型。正确的做法是回到变量选择上,看看是不是漏了某个关键解释变量。空间模型不是万能后悔药,它只解决空间依赖问题,解决不了变量缺失问题。

4.3 跑通一个 SLM 并用 AIC 对比 OLS

假设 LM 检验表明应该用 SLM。在 GeoDa 里操作路径是 Space → Regression → Spatial Lag,然后在变量设置里选同样的因变量和自变量,权重矩阵选之前生成并加载到当前工程的 .gal 文件。运行后你会得到新的系数估计和一组诊断指标。核心要比较的指标是 AIC(赤池信息准则)和 Log likelihood。AIC 越低说明模型在兼顾拟合度和复杂度之间表现越好,一般下降 2 以上才有实质意义。

下面用 Python 做一个同等的对比,这样你可以独立判断 GeoDa 的估计结果是否合理:

import geopandas as gpd from libpysal.weights import Queen from spreg import OLS, ML_Lag gdf = gpd.read_file("case_study/study_area.shp") w = Queen.from_dataframe(gdf, use_index=False) w.transform = "r" # 准备变量,X 需要手动加常数项 y = gdf["crime_rate"].values.reshape(-1, 1) X = gdf[["income", "education"]].values # OLS 基准模型 ols = OLS(y, X, w=w, name_y="crime_rate", name_x=["income", "education"]) print(f"OLS AIC: {ols.aic:.2f}") # 空间滞后模型(最大似然估计) lag = ML_Lag(y, X, w=w, name_y="crime_rate", name_x=["income", "education"]) print(f"SLM AIC: {lag.aic:.2f}") print(f"SLM 空间自回归系数 rho: {lag.rho[0]:.4f}")

这里的 ML_Lag 采用最大似然估计,和 GeoDa 的默认方法一致。rho 是空间自回归系数,代表邻居的因变量对当前区域的影响强度,它的符号和显著性才是你论文里真正要报告的核心结论。注意一个细节:spreg 的参数接口里,OLS 也可以传入权重矩阵,这样它会在诊断表里报告空间依赖指标,方便你对照 GeoDa 的输出。如果你在同一份数据上算出来的系数、AIC 与 GeoDa 差异明显,优先怀疑权重矩阵是否配对,而不是怀疑软件计算错误。

5. 解压、加载与结果失真的避坑记录:来自 zip 案例数据的前线日志

5.1 解压后路径含中文或过长,GeoDa 直接打不开或加载缓慢

现象:双击 shp 文件后 GeoDa 卡在加载界面,或者提示文件无法读取,但在资源管理器里明明能看到文件。

原因:GeoDa 对文件路径的编码处理不够健壮,中文字符和超长路径都会触发加载异常。尤其从 zip 解压后直接放在桌面并命名为「空间计量案例数据(最终版)」这类目录,最容易出问题。

解决:把整个解压文件夹移动到纯英文路径下,比如D:\geo\spatial_data,并且文件夹名字只保留英文。路径总长控制在 100 个字符以内。这是一个成本最低但见效最快的办法,90% 的加载失败都出在这个环节。

5.2 只解压了 .shp 文件,属性表打不开

现象:GeoDa 能显示地图轮廓,但打开属性表(Table)时字段列表是空的,或者直接报错说无法读取 .dbf。

原因:zip 包里的 .shp、.dbf、.shx 三个文件是配套的。很多解压工具在压缩包内文件较多时,如果你只拖出其中一个文件,其余文件没跟上,就会导致属性表缺失。另一个常见原因是解压工具对 .dbf 的编码识别错误,把包含中文字段的表读坏了。

解决:解压时不要从压缩包内单独拖文件,而是右键选择「解压到当前文件夹」。万一属性表还是打不开,用 Python 的 geopandas 重新读取并另存一份新 shp,让软件自动重建配套文件:

import geopandas as gpd gdf = gpd.read_file("case_study/study_area.shp") gdf.to_file("case_study/study_area_fixed.shp", encoding="utf-8")

这个操作会把坐标系、属性表、索引全部按现代标准重新写一遍,通常能解决大多数兼容性问题。另存时 attention 编码参数:如果原来的字段值包含中文,建议用encoding="utf-8",但如果你接下来还要用老版本 GIS 软件读取,可能需要改成"gbk",具体取决于你的下游工具链。

5.3 权重生成时提示字段有重复,或生成后莫兰指数样本数不对

现象:Tools → Weights Manager 里选了 ID 字段,点击 Create 后软件提示 non-unique values;或者在莫兰指数结果里显示的有效样本数比你地图里的区域数少好几个。

原因:ID 字段类型选错或数据本身有问题。常见的情形是你选了面积字段或人口字段作为 ID,而两个区域恰好面积相同,就会产生重复。另一个常见原因是 shp 的属性表里存在几何为空的多边形,这些区域在权重计算中会被自动跳过。

解决:先在属性表里确认一个唯一的短整数字段,没有的话用 GeoDa 的 Table → Add Column 添加一个,用公式生成行号。如果仍不正常,检查几何有效性:

import geopandas as gpd gdf = gpd.read_file("case_study/study_area.shp") invalid = gdf[~gdf.geometry.is_valid] print(f"无效几何数量: {len(invalid)}") if len(invalid) > 0: gdf["geometry"] = gdf.geometry.buffer(0) # 修复几何自相交 gdf.to_file("case_study/study_area_repaired.shp")

buffer(0) 是 GIS 领域修复无效几何的标准做法,它对自相交、断续线这类问题有奇效。注意执行后要重新生成权重矩阵,不要沿用旧的文件。

5.4 莫兰指数结果和论文里相差很大,可能是权重类型选错

现象:你用入门案例 zip 里的数据跑莫兰指数,得到的数值和教程里完全不一样,甚至符号都反了。

原因:不少入门案例包本身附带了一份「参考结果」,但参考结果用的可能是 Rook 权重或距离权重,而你用的是 Queen;还有可能是变量没有标准化,GeoDa 的默认操作会对变量做 z-score 标准化,如果你手动改了变量设置,差异就会放大。

解决:回到原始数据,确认教程或 README 里写的权重类型,逐项核对。如果 README 也没说,就分别用 Queen 和 Rook 各跑一次,看哪个结果和参考值更接近。这个差异本身就是一个很好的学习素材——同一份数据,因为空间关系定义方式不同,结论可能从显著变成不显著。这不是玄学,而是空间计量学的核心敏感性分析。

6. 把案例替换成自己的数据之前:三个检查动作和一项日常习惯

6.1 从 CSV 到 shp:让自己的数据进入 GeoDa 的标准路径

案例数据跑通之后,你大概率会想换自己的统计数据试试。最常见的格式是 CSV,里面有区域编码和变量列,但没有几何边界。要进入 GeoDa,首先需要把 CSV 合并到一份包含该区域边界的 shp 上。做法是先读入带边界的 shp 和一个纯属性 CSV,按区域编码字段做内连接,然后另存为新 shp。下面是一段可以直接改写的代码:

import geopandas as gpd import pandas as pd # 边界文件和属性文件 bounds = gpd.read_file("admin_boundary.shp") attrs = pd.read_csv("my_data.csv", encoding="utf-8") # 合并,region_code 是两个文件共有的字段 merged = bounds.merge(attrs, on="region_code", how="inner") # 检查是否有边界存在但属性缺失的区域 missing = bounds[~bounds["region_code"].isin(attrs["region_code"])] print(f"匹配后剩余区域: {len(merged)},缺失属性区域: {len(missing)}") merged.to_file("my_data_ready.shp", encoding="utf-8")

内连接是关键参数,它会丢掉那些有地图边界但没有统计数据的区域。这一步看似简单,实际上是最容易翻车的地方:行政区划调整导致两个年份的编码体系不一致,你已经按新的统计年鉴拿到的数据,在旧边界文件里找不到对应关系。所以在合并之前先打印一下缺失列表,人工看一眼缺失的区域是零星几个还是成片出现,成片出现通常意味着编码断代。

6.2 三个必查项:字段类型、缺失值和唯一标识

替换成自己的数据后,有三个检查动作我每次都会做,顺序不能乱。第一,把每个变量列在 GeoDa 的属性表里翻一遍,确认它们被识别成数值型而不是字符串型。导入时如果字段里有空值或中文逗号,整列会被识别成字符串,后续莫兰指数计算会直接报错。第二,用 Table → Summary 查看每个变量的缺失值数量和分布。缺失值超过 5% 的变量要谨慎使用,GeoDa 在空间回归中遇到缺失值会直接删掉整行记录,样本量悄然缩水,你可能还浑然不觉。第三,确认有没有一个全局唯一的 ID,不仅每个值不重复,而且长度不要超过 15 个字符,这是 GeoDa 生成权重文件时的经验安全线。

6.3 把权重文件当作和 shp 配套的「伴侣文件」管理

GeoDa 生成的 .gal 或 .gwt 文件不携带几何信息,它只保存了 ID 与 ID 之间的邻居关系。这意味着权重文件和 shp 的配对关系完全靠内部 ID 顺序维系。如果你把 shp 重新加工过,比如删掉了几个区域,或者改变字段顺序,原有的权重文件就失效了。虽然 GeoDa 不会主动报错,但计算时会出现样本对不齐甚至结果与地图不一致的问题。我的习惯是每一次修改数据后都重新生成权重,并且把权重文件改名为和 shp 同名(如study_area.shp对应study_area.gal),放在同一目录下,这样 GeoDa 在打开工程时更容易自动识别。

另外一个值得培养的工作习惯是每次跑完分析后,把 GeoDa 的工程文件连同 shp、权重文件一起归档为一个新 zip。这份归档材料加上你的操作日志,就是完整的论文复现材料。我从第一次跑空间计量到现在,吃过最亏的一次亏就是在和合作者反复调整数据时,把旧权重文件覆盖掉了,结果某一天跑出和前一日完全不同的莫兰指数,花了整整半天才发现是权重文件和新 shp 版本不配对。从那以后我不再信任任何「改了数据但没改权重」的工作流。这个学费交得值,也希望你不需要交第二次。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表