我们在研究跟省份有关的统计类数据时,往往会去分析不同省份的历史数据来判断其发展趋势,从而给出函数去预测未来几个月的数据。但有时候我们在画分布图或趋势图时,总能发现有些月份会出现奇怪的离散点,但又不能从自身数据挖掘出原因。
事实上,这类客观数据,我们其实可以考虑一下除了历史状态外,邻近区域的影响。比如有的省份隔壁刚刚举办了某大型研讨会,那么该领域的研究人员由于地域便利就可以去那里学习,提高区域内的创新能力,从数据上就可以看到在隔壁区域举行研讨会的后一个月份的论文产出量变高。
以下是一个例子:
# 加载必要的包
library(spdep) # 空间数据分析
library(ggplot2) # 绘图
# 设置随机种子(确保结果可复现)
set.seed(123)
# 生成模拟空间网格数据(10x10 网格)
n <- 10
grid <- expand.grid(x = 1:n, y = 1:n)
# 随机分配初始状态(1, 2, 3)
grid$state_initial <- sample(1:3, size = n^2, replace = TRUE, prob = c(0.6, 0.3, 0.1))
# 定义空间邻接关系(Queen 邻接:8 个邻居)
nb <- spdep::cell2nb(n, n, type = "queen")
W <- spdep::nb2mat(nb, style = "B") # 邻接矩阵(0/1)
# 模拟下一期状态(受邻居影响)
grid$state_next <- sapply(1:n^2, function(i) {
current_state <- grid$state_initial[i]
neighbors <- which(W[i, ] == 1) # 获取邻居索引
neighbor_states <- grid$state_initial[neighbors]
# 空间 Markov 规则:下一状态受当前状态 + 邻居状态影响
if (current_state == 1) {
# 如果当前是森林,且大多数邻居是城市 -> 可能转为城市
if (mean(neighbor_states == 3) > 0.5) {
sample(c(1, 3), size = 1, prob = c(0.3, 0.7))
} else {
sample(1:3, size = 1, prob = c(0.7, 0.2, 0.1))
}
} else if (current_state == 2) {
# 农田的转移逻辑
sample(1:3, size = 1, prob = c(0.2, 0.6, 0.2))
} else {
# 城市的转移逻辑
sample(1:3, size = 1, prob = c(0.1, 0.2, 0.7))
}
})
# 查看数据
head(grid)
# 计算传统 Markov 转移矩阵(忽略空间)
table("From" = grid$state_initial, "To" = grid$state_next) |> prop.table(margin = 1)
# 计算空间 Markov 转移矩阵(按邻居主要状态分组)
grid$neighbor_dominant <- sapply(1:n^2, function(i) {
neighbors <- which(W[i, ] == 1)
if (length(neighbors) == 0) return(NA)
tab <- table(grid$state_initial[neighbors])
as.integer(names(which.max(tab))) # 返回邻居的主要状态
})
# 按邻居主要状态分组计算转移概率
library(dplyr)
grid |>
filter(!is.na(neighbor_dominant)) |>
group_by(neighbor_dominant, state_initial) |>
summarise(
to_forest = mean(state_next == 1),
to_farm = mean(state_next == 2),
to_urban = mean(state_next == 3)
)
输出:
To
From 1 2 3
1 0.7333333 0.1500000 0.1166667
2 0.1515152 0.6060606 0.2424242
3 0.1428571 0.1428571 0.7142857
neighbor_dominant state_initial to_forest to_farm to_urban
<int> <int> <dbl> <dbl> <dbl>
1 1 1 0.787 0.106 0.106
2 1 2 0.192 0.577 0.231
3 1 3 0 0 1
4 2 1 0.538 0.308 0.154
5 2 2 0 0.833 0.167
6 2 3 0.333 0.333 0.333
7 3 2 0 0 1
从输出中可以看到,相比传统的markov链,虽然都是显示有多少的概率往森林、农田或城市方向转移,但运用了邻近区域的地方,比如隔壁是城市的话,会显示转为城市的概率为1,下一步百分百会往城市发展,因为隔壁城市会向外扩张,下一步百分百会往城市发展。