使用自定义函数调用terra::aggregate时出现“类型不兼容”错误
问题诊断与解决方案
错误原因
报错Not compatible with requested type: [type=list; target=double]的核心问题是:你的自定义聚合函数lc_aggr在部分分组中返回了列表类型,但terra::aggregate要求函数必须返回单个标量数值(double/整数类型)。内置的"modal"函数能正常运行,是因为它严格保证返回单个值,且处理了空分组、NA等边界情况。
修正后的自定义聚合函数
结合你的需求(水体值占比超75%才保留,否则返回次常见值),以下是修正后的lc_aggr函数:
lc_aggr <- function(x, drop = 0, threshold = 0.75) { # 过滤NA值 x <- x[!is.na(x)] # 处理全NA的空分组 if (length(x) == 0) return(NA_real_) # 统计值的频次并按降序排序 freq <- table(x) freq_df <- as.data.frame(freq, stringsAsFactors = FALSE) freq_df$Var1 <- as.numeric(freq_df$Var1) freq_df <- freq_df[order(-freq_df$Freq), ] # 计算最高频值的占比 total <- sum(freq_df$Freq) top_ratio <- freq_df$Freq[1] / total # 判断是否返回水体值 if (freq_df$Var1[1] == drop && top_ratio > threshold) { return(freq_df$Var1[1]) } else { # 只有一种值时返回该值,否则返回次常见值 return(ifelse(nrow(freq_df) >=2, freq_df$Var1[2], freq_df$Var1[1])) } }
关键修正点
- 明确过滤NA值,避免空分组引发的异常
- 将
table返回的结果转换为数值型DataFrame,杜绝列表结构输出 - 所有分支均返回单个标量(
NA_real_或单个数值),符合terra的要求 - 处理分组内仅有一种值的边界情况
测试运行
将上述函数加入你的代码,替换原lc_aggr后执行:
devtools::install_github("bcknr/rlandfire") library(rlandfire) library(terra) aoi <- c(-79.94116, 40.41411, -71.39884, 45.03770) products <- "130EVC" resolution <- 30 resp <- landfireAPI(products = products, aoi = aoi, resolution = resolution) dir.create(paste0(tempdir(),"/lf")) utils::unzip(resp$path, exdir = paste0(tempdir(),"/lf")) evc <- rast(paste0(tempdir(),"/lf/", resp$request$job_id,".tif")) values(evc)[values(evc) != 11] <- 1 values(evc)[values(evc) == 11] <- 0 # 加载修正后的聚合函数 lc_aggr <- function(x, drop = 0, threshold = 0.75) { x <- x[!is.na(x)] if (length(x) == 0) return(NA_real_) freq <- table(x) freq_df <- as.data.frame(freq, stringsAsFactors = FALSE) freq_df$Var1 <- as.numeric(freq_df$Var1) freq_df <- freq_df[order(-freq_df$Freq), ] total <- sum(freq_df$Freq) top_ratio <- freq_df$Freq[1] / total if (freq_df$Var1[1] == drop && top_ratio > threshold) { return(freq_df$Var1[1]) } else { return(ifelse(nrow(freq_df) >=2, freq_df$Var1[2], freq_df$Var1[1])) } } evc_aggr <- terra::aggregate(evc, fact = 33, fun = lc_aggr)
额外说明
- 若水体值不是
0,可通过terra::aggregate的...参数传递,例如:terra::aggregate(evc, fact=33, fun=lc_aggr, drop=11) - 调整占比阈值只需修改
threshold参数即可
内容的提问来源于stack exchange,提问作者mab
相关产品推荐
相关产品推荐

