使用while循环统计lidR分割树木点数量仅获首棵树数据的问题
问题原因
你代码的核心问题是每次循环都覆盖了原始的las对象:
第一次执行las <- filter_poi(las, treeID == 1)后,las就只剩treeID=1的点云数据了。后续循环i=2、3...时,在这个已经被过滤的las里根本找不到对应treeID的点,自然只能得到错误结果。
解决方案
方案1:修复循环逻辑(不推荐,效率低)
保留原始点云对象,每次基于原始数据过滤,不要修改原始las:
las <- segment_trees(las, watershed(chm, th_tree = 1, tol = 0.5, ext = 2)) # 先保存原始点云,避免被覆盖 original_las <- las pointlist <- list() # 先获取所有存在的treeID,避免循环到不存在的ID(比固定循环到1000更合理) all_treeIDs <- unique(original_las$treeID) for (tree_id in all_treeIDs) { current_las <- filter_poi(original_las, treeID == tree_id) point_count <- nrow(current_las) # 直接用nrow获取点数,比读header更简单 pointlist[[as.character(tree_id)]] <- point_count } pointlist
方案2:高效分组统计(强烈推荐)
R是向量式语言,用分组统计替代循环效率高得多,lidR和常用工具包都有现成方法:
方法A:用lidR自带的tree_metrics
专门针对treeID分组计算指标,最贴合lidR工作流:
las <- segment_trees(las, watershed(chm, th_tree = 1, tol = 0.5, ext = 2)) # 按treeID统计点数,结果是带treeID和n_points的LAS对象(或数据框) tree_point_counts <- tree_metrics(las, ~list(n_points = .N))
方法B:用dplyr分组统计
如果习惯tidyverse语法:
library(dplyr) las <- segment_trees(las, watershed(chm, th_tree = 1, tol = 0.5, ext = 2)) las_df <- as.data.frame(las) tree_point_counts <- las_df %>% group_by(treeID) %>% summarise(n_points = n())
方法C:用base R的table函数
最简单快速的方式,返回treeID和对应点数的表格:
las <- segment_trees(las, watershed(chm, th_tree = 1, tol = 0.5, ext = 2)) tree_point_counts <- table(las$treeID)
内容的提问来源于stack exchange,提问作者Purple_Ad
相关产品推荐
相关产品推荐

