自定义函数在lidR包部分函数中失效,pixel_metrics报错找不到函数
lidR中catalog_apply与pixel_metrics对自定义公式函数的解析差异问题
问题背景
个人开发的R包中包含适配lidR的自定义函数,参考lidR作者的写法,将my_metrics封装为公式形式的简写.my_metrics,定义如下:
#' @rdname my_metrics #' @export .my_metrics = ~my_metrics(X, Y, Z, ReturnNumber, Classification, ScanAngleRank, ht_slice=1, ht_max=NULL, min_pts=0, sar_thr=NULL)
使用catalog_apply调用cloud_metrics时该函数正常工作:
ads = clip_roi(ctg, shp, radius=shp$plot_rad) opt_chunk_buffer(ads) <- 0 opt_chunk_size(ads) <- 0 opt_output_files(ads) <- "" metrics = catalog_apply(ads, cloud_metrics, func = .my_metrics)
但调用pixel_metrics时却报错cannot find function "my_metrics",只有将my_metrics手动加载到全局环境才能正常执行:
r = pixel_metrics(ctg, .my_metrics, res = gridRes) # 错误: cannot find function "my_metrics"
已在包的DESCRIPTION文件的Depends部分添加lidR、terra、sf等依赖包。
原因分析
确实是catalog_apply与pixel_metrics的自定义函数解析机制存在差异:
catalog_apply执行时会继承调用时的环境(即你的R包命名空间环境),因此能正确找到包内定义的my_metrics函数。pixel_metrics处理公式形式的参数时,默认会在全局环境中查找公式内引用的函数,而非包的命名空间环境。当my_metrics仅存在于包内部时,全局环境无法定位到该函数,从而触发报错。
解决方案
方法1:显式指定函数的命名空间
修改.my_metrics的定义,在my_metrics前加上你的包名,强制公式从包的命名空间中查找函数:
#' @rdname my_metrics #' @export .my_metrics = ~你的包名::my_metrics(X, Y, Z, ReturnNumber, Classification, ScanAngleRank, ht_slice=1, ht_max=NULL, min_pts=0, sar_thr=NULL)
这种方式直接且不会污染全局环境,是推荐的解决方案。
方法2:绑定公式的执行环境
创建公式时明确指定其执行环境为你的包命名空间,确保pixel_metrics能在正确环境中查找函数:
#' @rdname my_metrics #' @export .my_metrics = as.formula( "~my_metrics(X, Y, Z, ReturnNumber, Classification, ScanAngleRank, ht_slice=1, ht_max=NULL, min_pts=0, sar_thr=NULL)", env = asNamespace("你的包名") )
该方式让公式的执行环境绑定到包的命名空间,避免依赖全局环境查找。
内容的提问来源于stack exchange,提问作者Nico
相关产品推荐
相关产品推荐

