R中clhs函数传入sf点时报错‘Not a matrix’,是否为bug?
问题分析与解决
核心问题
你遇到的错误并非bug,而是clhs()处理sf对象时,需要明确指定用于抽样的数值属性变量,而非直接传入整个sf点对象。虽然文档说明支持sf输入,但实际需要确保函数能正确识别sf对象中的属性列作为分层依据。
具体修复步骤
检查sf对象结构
你的smp是从栅格采样得到的sf点,属性表中仅包含树高这一数值列。clhs()需要基于这类数值属性完成分层抽样,所以要确保函数能访问到该属性。两种可行修复方式
- 方式一:提取sf对象的属性数据(剥离几何信息)传入,之后再从原始sf对象中匹配选中的样点
- 方式二:直接传入sf对象,显式指定用于分层的属性列名
修复后的可运行代码
## 加载必要包 library(clhs) library(terra) library(sf) ## 可复现设置 set.seed(78) ## 创建模拟树高栅格 fake_rast <- rast(xmin=-123.5, xmax=123.0, ymin=44.5, ymax=45.0, nrow=200, ncol=200, crs="EPSG:4326") values(fake_rast) <- rnorm(40000, 35, 10) ## 采样并转为sf对象 smp <- spatSample(fake_rast, 500, as.points=TRUE, na.rm=TRUE, replace=FALSE) %>% st_as_sf() ## 定义抽样参数 n <- 50 mi <- NULL temp <- 100 lc <- 10 ol <- 0.01 td <- 0.9 ## 修复方式1:提取属性矩阵,后续匹配原始样点 clhs.test1 <- clhs(x = st_drop_geometry(smp), size = n, temp=temp, iter=lc*log(ol/temp)/log(td), obj.limit=ol, tdecrease=td, length.cycle=lc, must.include=mi, use.cpp=TRUE, simple=FALSE) # 获取选中的样点 selected_points1 <- smp[clhs.test1$index_samples, ] ## 修复方式2:直接传入sf对象,显式指定分层变量 clhs.test2 <- clhs(x = smp, size = n, temp=temp, iter=lc*log(ol/temp)/log(td), obj.limit=ol, tdecrease=td, length.cycle=lc, must.include=mi, use.cpp=TRUE, simple=FALSE, vars = names(smp)) selected_points2 <- smp[clhs.test2$index_samples, ]
错误原因解释
- 直接传入sf对象时,若
clhs内部未正确识别属性列(部分版本对sf的支持存在细节兼容问题),会误判输入非数值矩阵,抛出Error: Not a matrix。 - 用
as.matrix()转换整个sf对象会包含几何信息(WKT格式文本),导致函数无法识别为有效数值输入,因此报错“不接受矩阵作为输入”。
内容的提问来源于stack exchange,提问作者Sean McKenzie
相关产品推荐
相关产品推荐

