You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在terra包中实现无监督分类:K-means与聚类指标计算问题

在terra中实现K-means聚类与最优簇数选择(无需频繁转换数据框)

1. 解决K-means报错问题

你的报错核心原因是直接将SpatRaster对象传入kmeans()——即使使用na.omit()处理,返回的仍是栅格对象,而base包的kmeans()仅支持数值矩阵或数据框输入。正确操作是先提取栅格数值并移除缺失值:

library(terra)
library(vegan)

set.seed(99)
# 提取栅格数值,移除含NA的行
clim_values <- na.omit(values(Clim))
# 运行K-means聚类
kmncluster <- kmeans(clim_values, centers = 5, iter.max = 500, nstart = 5)

2. 将聚类结果转回栅格

无需单独创建带单元格信息的数据框,直接基于原栅格的空间属性生成结果栅格:

# 复制原栅格的空间框架(取第一个波段即可)
cluster_raster <- Clim[[1]]
# 将聚类结果赋值给非NA的栅格单元格
cluster_raster[!is.na(Clim[[1]])] <- kmncluster$cluster

# 可视化结果
plot(cluster_raster, main = "K-means聚类结果")

3. 实现类似cascadeKM的最优簇数选择

直接用vegan::cascadeKM()处理提取的数值矩阵(无需将整个栅格转成数据框保存),同时计算Calinski或SSI指标:

方法1:用cascadeKM批量测试簇数

# 测试2-5类,基于Calinski指标
cascade_result <- cascadeKM(clim_values, 
                            inf.gr = 2, 
                            sup.gr = 5, 
                            iter = 100, 
                            criterion = "calinski")

# 查看结果(最优簇数对应最高的Calinski值)
print(cascade_result)
plot(cascade_result)

方法2:自定义循环计算指标(灵活控制)

如果需要同时计算SSI指标,可以手动循环不同簇数:

k_range <- 2:5
calinski_scores <- numeric(length(k_range))
ssi_scores <- numeric(length(k_range))

for (idx in seq_along(k_range)) {
  k <- k_range[idx]
  km_fit <- kmeans(clim_values, centers = k, iter.max = 500, nstart = 5)
  
  # 计算Calinski-Harabasz指数
  calinski_scores[idx] <- calinski(km_fit$cluster, clim_values)
  
  # 计算Simple Structure Index(SSI)
  ssi_scores[idx] <- vegan:::ssi(km_fit$centers, clim_values, km_fit$cluster)
}

# 输出指标结果
data.frame(
  簇数 = k_range,
  Calinski指数 = calinski_scores,
  SSI指数 = ssi_scores
)

关键注意事项

  • 始终用values(Clim)提取栅格的数值矩阵,这是连接terra与统计函数的核心步骤,无需将结果保存为单独的数据框。
  • na.omit()只对数值矩阵生效,直接用于SpatRaster只会返回移除了NA单元格的栅格,而非适合统计计算的数值格式。

内容的提问来源于stack exchange,提问作者Derek Corcoran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 12:10:17