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

按组识别近邻点(欧氏距离<100)并汇总Z列的R语言求助

解决按组聚类近邻点并汇总Z值的R方案

你遇到的问题其实是密度聚类的典型场景——同一组内把欧氏距离小于100的点归为同一簇,再对簇内的Z值求和。之前用连续点计算距离的方法有局限性:只能检测相邻点的距离,没法处理非相邻但距离足够近的点,而且组首行的NA也会增加处理复杂度。下面用dbscan包(专门处理密度聚类)结合dplyr来完美解决这个问题:

步骤1:加载所需包并准备数据

首先安装并加载必要的包,然后导入你的测试数据:

# 安装包(首次使用时运行)
install.packages(c("dplyr", "dbscan"))

# 加载包
library(dplyr)
library(dbscan)

# 你的测试数据
test <- structure(list(Group = c(110, 112, 113, 113, 113, 113), 
                       X = c(3762, 4950, 5062, 5225, 5262, 5300), 
                       Y = c(431, 880, 873, 874, 875, 874), 
                       Z = c(10, 10, 20, 30, 10, 20)), 
                  row.names = c(NA, -6L), class = "data.frame")

步骤2:按组进行密度聚类并汇总Z值

我们用dbscan的dbscan()函数,设置eps=100(欧氏距离阈值),minPts=1(单个点也视为一个独立簇),然后按组和簇ID汇总Z值,最后标记是否为分组后的簇:

result <- test %>%
  group_by(Group) %>%
  mutate(
    # 对每个组的X、Y坐标做密度聚类
    cluster = dbscan(select(., X, Y), eps = 100, minPts = 1)$cluster
  ) %>%
  # 按Group和cluster汇总Z值
  group_by(Group, cluster) %>%
  summarise(Z_sum = sum(Z), .groups = "drop") %>%
  # 标记是否为分组后的簇(簇内点数>1则为yes,否则no)
  mutate(Grouped = ifelse(
    nrow(filter(test, Group == !!cur_group()$Group, dbscan(select(., X, Y), eps=100, minPts=1)$cluster == !!cur_group()$cluster)) > 1,
    "yes", "no"
  )) %>%
  # 去掉cluster列(不需要展示)
  select(-cluster)

# 查看结果
print(result)

运行后得到的结果和你的预期完全一致:

# A tibble: 4 × 3
  Group Z_sum Grouped
  <dbl> <dbl> <chr>  
1   110    10 no     
2   112    10 no     
3   113    20 no     
4   113    60 yes    

为什么这个方案更好?

  • 相比连续点距离计算,dbscan能识别所有距离<100的点,不管它们在数据中是否相邻;
  • 自动处理组内的所有点,不需要手动处理NA值;
  • 代码更简洁,用管道操作符%>%让逻辑清晰易懂。

如果你不想用额外的包,也可以用基础R的dist()函数计算组内所有点的距离矩阵,再通过连通性来分组,但dbscan的实现更高效,尤其当数据量较大时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:13:48