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

如何在R语言中获取距离矩阵每行的最小值、第二小值及对应点ID

如何获取距离矩阵每行的最小值、第二小值及对应列名?

先回顾下你的距离矩阵头部数据:

head(distances)
2914 2915 2924 2953 2954 2988 2989 3183 3184 3341
317_1 11116.25 10534.133 12759.250 2418.834 8386.288 9123.886 9573.037 4396.882 9179.407 3420.459
317_2 10827.64 10003.469 12307.238 1996.878 7994.617 8543.298 9006.385 4795.352 9363.853 3804.140
317_3 13544.06 10036.287 7341.391 3079.408 2918.336 7298.468 8283.268 9861.902 14234.768 8875.232
317_4 13495.06 9859.046 7102.862 3271.923 2744.106 7081.206 8082.261 10058.709 14362.919 9069.278
317_5 14652.07 11234.219 7378.551 3642.721 2782.711 8468.613 9469.082 10257.441 14899.174 9292.621
317_6 14796.52 11265.946 7108.030 3893.178 2511.896 8458.536 9476.372 10530.603 15150.529 9564.130

你已经通过这段代码实现了每行最小值、对应点ID和聚类ID的提取:

result <- t(sapply(seq(nrow(distances)), function(z) {
  j <- which.min(distances[z,])
  c(rownames(distances)[z], colnames(distances)[j], distances[z,j])
}))
min_dist1 <- as.data.frame(result)
colnames(min_dist1) <- c("cluster_id", "point_id", "min_dist")
# min_dist单位为米

现在要新增第二小距离和对应点ID的列,这里给你两种实用的解决方案:

方案一:基于排序的直观实现

这个方法逻辑清晰,把每行数据转成带列名的小数据框,排序后直接提取前两位结果,后续要扩展到前N小值也很方便:

result <- t(sapply(seq(nrow(distances)), function(z) {
  # 将当前行转换为带列名的数据框,方便关联点ID和距离
  row_df <- data.frame(
    point_id = colnames(distances),
    dist = as.numeric(distances[z,]),
    stringsAsFactors = FALSE
  )
  # 按距离升序排序
  sorted_row <- row_df[order(row_df$dist), ]
  
  # 提取所需的聚类ID、最小/第二小的点ID和距离
  c(
    rownames(distances)[z],
    sorted_row$point_id[1], sorted_row$dist[1],
    sorted_row$point_id[2], sorted_row$dist[2]
  )
}))

# 转换为数据框并设置列名
final_result <- as.data.frame(result, stringsAsFactors = FALSE)
colnames(final_result) <- c(
  "cluster_id", "min_point_id", "min_dist",
  "second_min_point_id", "second_min_dist"
)

# 把距离列转为数值型(因为sapply返回的是字符矩阵)
final_result$min_dist <- as.numeric(final_result$min_dist)
final_result$second_min_dist <- as.numeric(final_result$second_min_dist)

方案二:基于索引的高效实现

如果追求更高效率,可以直接操作向量索引,避免数据框转换的开销:

result <- t(sapply(seq(nrow(distances)), function(z) {
  row_vals <- as.numeric(distances[z,])
  # 获取按距离升序排列的索引
  sorted_indices <- order(row_vals)
  
  # 提取最小和第二小值对应的索引
  min_idx <- sorted_indices[1]
  second_min_idx <- sorted_indices[2]
  
  # 组装结果
  c(
    rownames(distances)[z],
    colnames(distances)[min_idx], row_vals[min_idx],
    colnames(distances)[second_min_idx], row_vals[second_min_idx]
  )
}))

final_result <- as.data.frame(result, stringsAsFactors = FALSE)
colnames(final_result) <- c(
  "cluster_id", "min_point_id", "min_dist",
  "second_min_point_id", "second_min_dist"
)

# 批量转换距离列为数值型
final_result[, c("min_dist", "second_min_dist")] <- lapply(
  final_result[, c("min_dist", "second_min_dist")], as.numeric
)

注意事项

  • 一定要把距离列转为数值型:因为sapply返回的是字符矩阵,直接转成数据框后距离会是字符类型,后续统计计算会出错。
  • 如果矩阵中存在重复的最小值,which.min只会返回第一个出现的索引,而排序方案会保留排序后的顺序;如果需要处理重复值场景,可以根据需求调整提取逻辑(比如先筛选所有最小值,再取剩余值中的最小)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 14:32:28