空间共位分析 · 原理与参数详解
空间共位分析 · 原理与参数详解
这篇是给谁看的
如果你只是想快速跑一次分析、拿到结果,去看 空间共位分析(快速上手版) 就够了。
但如果你在分析完之后,心里冒出了这些问题:
- LCLQ 值到底是怎么算出来的?为什么有的大于 1、有的小于 1?
- P 值 0.03 和 0.07 到底差在哪?0.05 这条线是谁定的?
- 核函数选高斯还是 Bisquare,对结果到底有多大影响?
- 全局 CLQ 矩阵不对称是什么意思?A→B 和 B→A 为什么不一样?
- Cross-K 曲线上面那条灰色带怎么看?
- "参与指数"到底衡量的是什么?
那这篇详解就是为你准备的。我会把每个术语、每个参数、每条结果背后的逻辑讲清楚。不用你有任何统计学基础 —— 该翻译成人话的地方,我一定翻译。
第一部分:核心概念
什么是"空间共位"
"空间共位"(Spatial Colocation)说的是一种现象:两类(或多类)地理要素,在空间上倾向于出现在彼此附近。
举个生活中的例子。你走在街上,发现便利店旁边经常有奶茶店。如果这只是你主观的印象,那不算数 —— 可能只是因为商业区本身什么店都多。但如果拿出数据一算,发现便利店附近出现奶茶店的概率,确实比随机预期高出很多,而且这个"高出"经过了统计检验 —— 那我们就说"便利店和奶茶店存在显著的空间共位关系"。
注意几个要点:
- 共位不等于因果。便利店和奶茶店扎堆,不代表"因为有便利店所以开了奶茶店",只能说明它们之间存在空间关联
- 共位是有方向的。A 附近 B 多,不代表 B 附近 A 也多(后面详细解释)
- 共位可以是正向的(扎堆),也可以是负向的(互相远离)
为什么不能直接数"附近有几个"
你可能会想:直接数一数每家便利店旁边有多少家奶茶店不就行了?
问题在于:不同区域的点密度不一样。 在市中心,方圆 500 米内可能有 20 家各种各样的店;在郊区,方圆 500 米可能只有 3 家。如果你单纯看"附近有几家奶茶店",市中心的便利店一定比郊区多 —— 但这只是因为市中心什么都多,不是因为便利店和奶茶店有特殊关系。
所以需要一个指标,能"消除密度影响",只衡量"比随机预期多了多少"。这就是共位商(Colocation Quotient)做的事。
第二部分:四种分析方法的原理
方法一:局部共位商(LCLQ)
LCLQ 是 Local Colocation Quotient 的缩写,中文叫"局部协同区位商"。它是这套分析工具里最核心的方法。
计算逻辑
对于数据中的每一个 A 类点 $i$,LCLQ 的计算分三步:
第一步:看邻居里有多少个 B
找到点 $i$ 的 K 个最近邻居(或者距离带内的所有邻居),数一数其中有多少个是 B 类。但不是简单地数个数 —— 每个邻居有一个权重,离得近的权重大、离得远的权重小。
用公式写就是:
$$N_{B}^{(i)} = \frac{\sum_{j \in \text{邻居}} w_{ij} \cdot \mathbb{1}(j \text{是B类})}{\sum_{j \in \text{邻居}} w_{ij}}$$
翻译一下:在点 $i$ 的所有邻居中,B 类邻居的加权比例。
第二步:和随机期望值比较
如果所有点的类别是随机分配的,那么邻居中 B 类的期望比例就等于整体数据中 B 类的比例。
$$E_B = \frac{\text{B 类点的总数}}{\text{总点数} - 1}$$
减 1 是因为要排除点 $i$ 自己。
第三步:两者相除
$$LCLQ_i = \frac{N_{B}^{(i)}}{E_B}$$
- LCLQ > 1:这个点附近 B 类比预期多 → 正向共位(扎堆)
- LCLQ = 1:和随机预期一致 → 没有特殊关联
- LCLQ < 1:这个点附近 B 类比预期少 → 负向共位(互相远离)
一个具体的例子
假设你的数据有 100 个点,其中 30 个是便利店(A),40 个是奶茶店(B),30 个是药店。
现在看便利店 $i$,它最近的 10 个邻居里有 6 个是奶茶店。
- $N_B^{(i)} = 6/10 = 0.6$(邻居中奶茶店占 60%)
- $E_B = 40/99 ≈ 0.404$(整体中奶茶店占 40.4%)
- $LCLQ_i = 0.6 / 0.404 ≈ 1.49$
LCLQ = 1.49,大于 1 —— 说明这家便利店附近的奶茶店比随机预期多了约 49%。
但别急着下结论。光看这个数字还不够,还得做显著性检验。
为什么 LCLQ 是有方向的
A→B 的 LCLQ 和 B→A 的 LCLQ 是不一样的。
因为"便利店附近奶茶店多不多"和"奶茶店附近便利店多不多"是两个不同的问题。A→B 看的是 A 类点的邻居中 B 的比例,B→A 看的是 B 类点的邻居中 A 的比例。
两者不对称是正常的。比如一个商圈里有 3 家便利店和 30 家奶茶店 —— 每家便利店旁边确实围了一堆奶茶店(A→B 高),但每家奶茶店旁边不一定有便利店(B→A 可能不高)。
方法二:全局共位商矩阵(Global CLQ)
如果你的数据有 5 种类型(便利店、奶茶店、药店、餐厅、书店),那两两组合就有 5×5=25 对方向关系。一对对手动跑 LCLQ 太累了。
全局 CLQ 矩阵帮你一次性算完所有类别对的关联强度。
计算逻辑
对于每一对(A→B),全局 CLQ 就是所有 A 类点的 LCLQ 均值:
$$CLQ_{A \to B} = \frac{1}{|A|} \sum_{i \in A} LCLQ_i$$
结果是一张 N×N 的矩阵(N = 类别数),每个格子就是一个方向的全局共位商。
怎么看这张矩阵
- 对角线是灰色 / NaN —— 自己和自己的共位没意义
- 格子颜色深(CLQ 远大于 1)—— 这对关联很强
- 格子颜色浅(CLQ 接近或小于 1)—— 这对没什么特殊关系
- 矩阵不对称是正常的 —— A→B ≠ B→A(原因上面解释过了)
- 带星号或特殊标记的格子 —— 通过了显著性检验(P < 0.05)
💡 实际使用建议:先看全局矩阵找到最值得关注的类别对(颜色最深、且显著的那几格),再切换到「局部 LCLQ」模式深入分析这些对 —— 看看具体哪些区域的共位最强。
方法三:共位模式挖掘(Colocation Pattern Mining)
前两种方法都需要你事先指定"看哪两类"。但如果你的数据有 20 种 POI 类别,两两组合有 380 对 —— 你怎么知道该看哪对?
共位模式挖掘不需要你指定。它会自动扫描所有类别组合,找出"哪些类别总是出现在彼此附近"。
算法原理
地图帮实现的是 Joinless 算法(Yoo & Shekhar, 2006),这是空间数据挖掘领域的经典方法。核心思路:
第一步:建邻域
对每个点,找到它的 K 个最近邻。这样每个点就有了一个"邻域"列表。
第二步:找实例
如果某个点的邻域里同时出现了类别 X 和类别 Y,那这个点就是 {X, Y} 这个模式的一个"实例"。
第三步:算参与率
对于模式 {X, Y},分别看:
- 所有 X 类点中,有多少个的邻域里有 Y?这个比例叫 X 的参与率
- 所有 Y 类点中,有多少个的邻域里有 X?这个比例叫 Y 的参与率
两者取最小值,就是这个模式的参与指数(Participation Index):
$$PI({X, Y}) = \min\left(\frac{|{x \in X : x \text{的邻域有Y}}|}{|X|}, \frac{|{y \in Y : y \text{的邻域有X}}|}{|Y|}\right)$$
取最小值是为了保守 —— 两边都得有足够多的点参与,才算真正的共位。
第四步:剪枝
如果一个 2 阶模式(两类)的参与指数低于阈值,那包含这两类的 3 阶模式(三类)一定也低于阈值 —— 这叫 Apriori 性质。利用这个特点可以大幅减少计算量,不用把所有高阶组合都算一遍。
结果怎么理解
- 模式 {便利店, 奶茶店},参与指数 0.65 —— 意思是:65% 的便利店旁边有奶茶店,同时至少 65% 的奶茶店旁边有便利店
- 模式 {便利店, 奶茶店, 药店},参与指数 0.40 —— 三类同时出现在一起的情况,参与指数通常比两两的低,因为要求更严格
- 阶数越高(3 阶、4 阶),模式越少,但发现的关联越有意思
方法四:Cross-K 函数(多尺度分析)
前面三种方法都有一个隐含的设定:你要事先决定"看多远"的邻居(K 值或距离带)。但如果你不知道两类要素在什么距离上关联最强呢?
Cross-K 函数就是解决这个问题的。它不固定一个距离,而是从近到远,在多个距离尺度上逐个检测共位强度,画出一条曲线。
算法原理
Cross-K 函数是经典的 Ripley's K 函数的双变量扩展。原始 K 函数分析的是"一类点自己和自己的聚集程度",Cross-K 分析的是"两类点之间的聚集程度"。
对于距离阈值 $d$:
$$K_{AB}(d) = \frac{|S|}{|A| \cdot |B|} \sum_{i \in A} \sum_{j \in B} \mathbb{1}(d_{ij} \leq d)$$
翻译一下:在距离 $d$ 范围内,A 类点和 B 类点之间有多少对?除以总数做标准化。
Cross-L 函数
K 函数的值不太直观(随距离增大而快速增大),所以通常做一个变换:
$$L_{AB}(d) = \sqrt{K_{AB}(d) / \pi} - d$$
变换后:
- $L(d) > 0$:在距离 $d$ 上,A 和 B 的聚集程度超出随机预期 → 正向共位
- $L(d) = 0$:和随机预期一致
- $L(d) < 0$:在距离 $d$ 上,A 和 B 比随机预期更分散 → 负向共位
置信包络
光看 L 值是正还是负还不够 —— 也可能只是随机波动。
系统会做多次置换检验(把所有点的类别标签随机打乱,重新计算 K/L 曲线),得到一组模拟曲线。把每个距离上的模拟值排序,取 2.5% 和 97.5% 分位数,就形成了一条灰色的置信包络带。
- 实线在灰色带上方 → 这个距离上的共位显著(超出了 95% 的随机波动范围)
- 实线在灰色带内部 → 不显著(可能只是随机的)
- 实线在灰色带下方 → 显著的负向共位(两类互相远离)
峰值距离
曲线的最高点对应的距离,就是"共位最强的空间尺度"。比如峰值在 800 米,说明便利店和奶茶店在 800 米范围内的空间关联最强。
第三部分:参数详解
分类字段
就是你数据中用来区分不同类型的那一列。
比如你的数据有"名称""地址""类型""经度""纬度"这几列,那分类字段就应该选"类型"。
⚠️ 分类字段必须是有重复值的列。如果你选了"名称"这种每行都不一样的列,系统会认为你有几百种类别,每种只有一个点 —— 跑出来的结果没有任何意义。
邻域类型
邻域定义了"看多远的邻居",是所有空间分析的基础设定。
KNN(K 近邻)
每个点只看离它最近的 K 个邻居,不管这 K 个邻居有多远。
- 优点:每个点的邻居数量固定,结果稳定
- 缺点:在密集区域,K 个邻居可能挤在 100 米内;在稀疏区域,K 个邻居可能散布在 5 公里外。同一个 K 值对应的实际空间尺度不一样
- 推荐 K 值:5~15。太小(2~3)噪声大、容易被个别点影响;太大(超过总点数的 1/3)会把远处不相关的点也拉进来
- 什么时候用:数据密度比较均匀的时候,或者你不确定该设多大距离的时候
距离带(Distance Band)
每个点看固定半径范围内的所有邻居,不管有多少个。
- 优点:空间尺度一致 —— 1000 米就是 1000 米,不会因为密度不同而变化
- 缺点:密集区域邻居可能有几十个,稀疏区域可能只有 1 个甚至 0 个(没有邻居的点无法计算 LCLQ)
- 推荐距离:取决于你的数据。系统在参数页面会给出一个推荐值,是根据数据点之间的距离分布自动计算的
- 什么时候用:当你关心的是"固定范围内的关联"(比如"500 米步行范围内"),或者数据密度差异很大的时候
💡 不确定用哪个?先用 KNN,K=8。大多数情况下效果都不错。
核函数
核函数决定了邻居的权重衰减方式 —— 是离得远的邻居权重骤降,还是缓慢下降,还是所有邻居一视同仁。
高斯核(Gaussian)
$$w(d) = \exp\left(-\frac{d^2}{2h^2}\right)$$
权重随距离平滑衰减,永远不会完全降到 0(但离得很远时已经趋近于 0)。
- 最常用,适合大多数场景
- 衰减速度取决于带宽 $h$(KNN 模式下自动取第 K 近邻的距离,距离带模式下就是你设的半径)
Bisquare 核
$$w(d) = \begin{cases} \left(1 - \frac{d^2}{h^2}\right)^2 & d \leq h \ 0 & d > h \end{cases}$$
权重随距离衰减,但超过带宽 $h$ 后直接归零。
- 比高斯核有"明确截断" —— 超出一定距离的点完全不考虑
- 特别适合距离带邻域,因为距离带本身就有一个明确的半径
- 如果你认为"超过一定距离就不应该有影响",选这个
均匀核(Uniform)
$$w(d) = 1$$
所有邻居权重相同,不管远近。
- 最简单,计算最快
- 适合你只关心"有没有在附近",不关心"离得多近"的场景
- 相当于传统的"数个数"方法
💡 不确定用哪个?用高斯核。它是最平滑、最不容易出问题的选择。
置换检验次数
置换检验(Permutation Test)是用来判断你观测到的 LCLQ 值是不是"碰巧"的。
原理
把所有点的类别标签随机打乱(保持位置不变),重新算一遍 LCLQ。重复很多次,就得到了一个"随机情况下 LCLQ 的分布"。
然后看你真实的 LCLQ 值在这个分布里排第几:如果比 95% 的随机值都大,那 P 值就小于 0.05,说明这个共位关系不太可能是偶然的。
次数怎么选
| 次数 | 速度 | 精度 | 适用场景 |
|---|---|---|---|
| 99 | 快 | P 值精度到 0.01 | 试探性分析,先看看大致结果 |
| 199 | 中等 | P 值精度到 0.005 | 比较正式的分析 |
| 499 | 较慢 | P 值精度到 0.002 | 标准的学术分析 |
| 999 | 慢 | P 值精度到 0.001 | 发表论文级别 |
第一次跑先用 99,确认参数没问题后再调高。最终出结果建议用 499 或 999。
⚠️ 置换次数和数据量共同决定计算时间。100 个点 × 99 次置换通常几秒搞定;1000 个点 × 999 次可能需要几分钟。
最小参与率阈值(仅模式挖掘)
只在「共位模式挖掘」模式下用到。
参与指数低于这个阈值的模式会被过滤掉。比如你设了 0.5,那只有至少 50% 的相关点都参与了共位的模式才会保留。
- 0.5:标准值,适合大多数场景
- 0.3:宽松一些,会发现更多模式(包括一些较弱的关联)
- 0.7:严格,只保留非常强的关联
💡 如果跑出来 0 个模式,别慌 —— 降低阈值到 0.2~0.3 再试。数据量小的时候,真正强共位的模式可能就是少。
距离步数和最大距离(仅 Cross-K)
只在「Cross-K 多尺度分析」模式下用到。
- 距离步数:把从 0 到最大距离的范围分成多少段来计算。步数越多曲线越平滑,但计算越慢。10~20 步通常够用
- 最大距离:分析到多远。系统默认取数据范围的 1/4,一般不用改
第四部分:结果字段详解
局部 LCLQ 结果表
分析完成后,你的数据表会多出这些列:
| 列名 | 含义 | 怎么看 |
|---|---|---|
| LCLQ | 局部共位商 | > 1 = 附近 B 多,< 1 = 附近 B 少,= 1 = 随机 |
| PVALUE | P 值 | < 0.05 通常认为显著。越小越确定 |
| LCLQBIN | 显著性分类编号 | 0=显著共位,1=共位不显著,2=显著孤立,3=孤立不显著 |
| LCLQTYPE | 显著性分类标签 | 上面编号的中文说明 |
| CLQ_A_B | 全局共位商 | 所有 A 类点的 LCLQ 均值(每行都一样) |
| NEIGHCATS_cnt | 邻居中 B 的加权比例 | 用于核查计算过程,一般不用看 |
四种显著性分类是什么意思
地图上的四种颜色,对应结果表中 LCLQBIN 的四种取值:
0 —— 显著共位(Colocated & Significant)🔴
LCLQ > 1 且 P < 0.05。这个点附近 B 类确实比随机预期多,而且通过了统计检验。这是你最关心的结果 —— 它标记的就是"共位真正发生的地方"。
1 —— 共位但不显著(Colocated & Not Significant)🟠
LCLQ > 1 但 P ≥ 0.05。看起来附近 B 多,但统计上不够确定 —— 可能只是碰巧。
2 —— 显著孤立(Isolated & Significant)🔵
LCLQ < 1 且 P < 0.05。这个点附近 B 类确实比预期少,而且统计确认了。说明这个位置对 B 类有某种"排斥"效应。
3 —— 孤立但不显著(Isolated & Not Significant)⚪
LCLQ < 1 但 P ≥ 0.05。附近 B 类偏少,但不确定是不是偶然。
💡 一般来说,你主要关注类型 0(红色)和类型 2(蓝色)。它们是经过统计检验的可靠结论。橙色和灰色可以作为参考,但不要据此做重要决策。
P 值到底怎么理解
P 值可能是整个分析里最容易误解的东西。这里用大白话讲一次:
P 值 = 在"A 和 B 没有关系"的假设下,你观测到的结果(或更极端的结果)出现的概率。
换句话说:
- P = 0.03 —— 如果 A 和 B 真的没关系,那你看到的这种结果只有 3% 的概率出现。3% 太小了,所以你有理由怀疑"没关系"这个假设是错的 → 结论:可能真的有关系
- P = 0.20 —— 如果没关系,这种结果有 20% 的概率出现。20% 不算小,可能就是碰巧 → 结论:证据不够
0.05 这条线是谁定的?
这是学术界的惯例,不是自然规律。0.05 只是一个"大家普遍能接受的门槛"。有些领域用 0.01(更严格),有些用 0.10(更宽松)。在实际业务中,你可以根据决策的严重程度灵活掌握:
- 做学术研究 → 严格按 0.05
- 做商业选址参考 → 0.10 也可以接受
- 做高风险决策(比如医疗) → 最好用 0.01
⚠️ P 值不是"A 和 B 有关系的概率"。这是一个非常常见的误解。P=0.03 不是说"有 97% 的概率有关系"。统计学没有这么简单,但在实际使用中,你可以大致理解为"证据越强,P 值越小"。
第五部分:常见疑问
"我的数据不是经纬度,是高德坐标 / 百度坐标,能用吗?"
能用,但建议先做坐标转换。
地图帮的共位分析在计算距离时,会把经纬度转换成笛卡尔坐标(三维直角坐标系),然后用欧氏距离做近邻搜索。这种方法在小范围内(一个城市或一个省)精度完全够用,但前提是你的坐标是标准的 WGS84 经纬度。
高德坐标(GCJ02)和百度坐标(BD09)都做了偏移加密,直接用会导致距离计算有几十到几百米的误差。对于 K=5~10、距离带 1000 米以上的分析,这个误差通常影响不大。但如果你追求严谨,建议先用地图帮的 坐标系转换 工具转成 WGS84。
"数据量有什么限制?"
理论上没有硬性上限,但:
- 50 条以下:置换检验不稳定,P 值参考价值低
- 100~500 条:比较理想的范围,结果可靠,速度也快
- 500~2000 条:没问题,置换次数建议先用 99
- 2000 条以上:可以跑,但置换检验会比较慢。建议先用低置换次数测试参数,确认没问题再调高
"全局 CLQ 和平均 LCLQ 什么关系?"
全局 CLQ 就是所有 A 类点的 LCLQ 均值。所以:
- 全局 CLQ > 1 → 整体来看 A 附近 B 偏多
- 全局 CLQ ≈ 1 → 整体上没有特殊关联
- 全局 CLQ < 1 → 整体来看 A 附近 B 偏少
但全局 CLQ 可能掩盖空间异质性 —— 也许城北的便利店旁边奶茶店特别多,城南特别少,平均下来正好约等于 1。所以全局 CLQ 只是概览,真正有价值的是看局部 LCLQ 的空间分布。
"模式挖掘的参与指数和 LCLQ 有什么区别?"
两个指标衡量的东西不一样:
- LCLQ:对每个具体的点,衡量"这个点附近 B 类是否偏多"
- 参与指数:对一个类别组合,衡量"这两类(或多类)是否普遍地出现在彼此附近"
参与指数是一个全局汇总指标,不区分具体哪个点。LCLQ 是逐点计算的局部指标。
一般的使用路径是:先用模式挖掘发现值得关注的类别对,再切换到 LCLQ 模式深入分析具体哪些区域的共位最强。
"Cross-K 的峰值距离和 K 值 / 距离带怎么配合?"
一个很好的实践方法:
- 先跑 Cross-K,找到峰值距离(比如 800 米)
- 然后用「距离带」邻域 + 800 米半径跑局部 LCLQ
- 这样你的 LCLQ 分析就精确锁定在了"共位最强的空间尺度"上
这比凭感觉设 K 值要科学得多。
"结果全是不显著,是不是软件出了问题?"
大概率不是。全不显著说明你的两类要素之间确实不存在显著的空间关联 —— 这本身也是一个有价值的结论。
但在下结论之前,先排查几个常见原因:
- 数据量太小 —— 低于 50 条时,置换检验的统计功效很低,即使有真实的共位也可能检测不出来
- K 值不合适 —— K 太大会把远处不相关的点拉进来,稀释真实的局部共位信号
- 类别太细 —— 如果每种类别只有几个点,统计检验很难达到显著水平
- 本来就没有关系 —— 这完全正常。"没有显著关联"也是一种发现
第六部分:学术背景
如果你要在论文或报告里引用这个方法,以下是核心参考文献:
- LCLQ 方法:Wang, F., Hu, Y., Wang, S. & Li, X. (2017). "Local Indicator of Colocation Quotient with a Statistical Significance Test." The Professional Geographer, 69(1), 22-31.
- 全局 CLQ:Leslie, T.F. & Kronenfeld, B.J. (2011). "The Colocation Quotient: A New Measure of Spatial Association Between Categorical Subsets of Points." Geographical Analysis, 43(3), 306-326.
- Joinless 模式挖掘:Yoo, J.S. & Shekhar, S. (2006). "A Joinless Approach for Mining Spatial Colocation Patterns." IEEE TKDE, 18(10), 1323-1337.
- Cross-K 函数:Ripley, B.D. (1977). "Modelling Spatial Patterns." Journal of the Royal Statistical Society B, 39(2), 172-212.
在报告中描述分析方法时,可以这样写:
空间共位分析采用局部协同区位商方法(LCLQ, Wang et al. 2017),以 K=8 的 KNN 邻域和高斯核函数计算局部共位商,并通过 999 次置换检验在 α=0.05 水平判断显著性。
做完了,检查一下
如果你把这篇详解从头读到这里——恭喜,你现在对空间共位分析的理解已经不输于大多数 GIS 从业者了。
回到 快速上手版 再跑一次分析,你会发现每个参数、每个结果字段都变得有意义了。
看到 LCLQ=1.49 你知道它意味着"比随机多了 49%";看到 P=0.03 你知道这个结论有多可靠;看到 Cross-K 曲线的峰值你知道该用什么距离去做进一步分析。
数据分析的价值不在于跑出一堆数字,而在于你知道每个数字在说什么。
