如何从R数据框中选取n个具有最大欧氏分散度的行?
多维数据高分散度行提取方案
问题说明
给定如下多维数据框:
df <- data.frame(a = runif(100, -10, 10), b = runif(100, -10, 10), c = runif(100, -10, 10), d = runif(100, -10, 10), e = runif(100, -10, 10))
需要实现一个函数,从中提取n个在y维空间内欧氏距离分散度最大的行索引。一维场景示例:
- 输入
c(1:9),调用函数应返回c(1,5,9)(提取3个点) - 输入
c(1:9),调用函数应返回c(1,3,5,7,9)(提取5个点) - 输入
c(1:10),调用函数可随机返回c(1,5,10)或c(1,6,9)(提取3个点)
原有方案的问题
此前实现的voronoiFilter函数仅支持二维数据,且因重复数据频繁触发警告:
voronoiFilter <- function(occ, select){ n <- nrow(occ) - select subset <- occ dropped <- rep(NA, n) for (i in 1:n) { v <- voronoi.mosaic(x = subset[,1], y = subset[,2], duplicate = "remove") info <- cells(v) areas <- unlist(lapply(info,function(x) x$area)) smallest <- which(areas == min(areas, na.rm = TRUE)) dropped[i] <- which(occ[,1] == subset[smallest,1] & occ[,2] == subset[smallest,2]) subset <- subset[-smallest,] } outVec <- 1:nrow(occ) return(outVec[-dropped]) }
触发的警告信息:
Warning in hist.default(i, plot = FALSE, freq = TRUE, breaks = seq(0.5, : argument ‘freq’ is not made use of
替代实现方案
推荐使用最大最小距离(MaxMin)贪心算法,该算法适用于任意维度,且能有效处理重复数据,核心逻辑是每次选择离已选样本集合最远的点,最终得到分散度最大的样本集。
实现代码
maxmin_sample <- function(data, n) { # 转换为矩阵处理,确保数值型格式 data_mat <- as.matrix(data) # 处理重复行:保留唯一行并后续映射回原始索引 unique_data <- unique(data_mat) if (nrow(unique_data) < n) { stop("数据中唯一样本数量小于需要提取的n值") } # 初始化:随机选择第一个样本的索引 selected_idx <- sample(1:nrow(unique_data), 1) # 迭代选择剩余n-1个样本 for (i in 2:n) { # 计算每个未选点到已选点的最小距离 dist_mat <- dist(rbind(unique_data[selected_idx, ], unique_data)) min_dist <- apply(as.matrix(dist_mat)[1:length(selected_idx), -(1:length(selected_idx))], 2, min) # 选择最小距离最大的点加入已选集合 next_idx <- which.max(min_dist) + length(selected_idx) selected_idx <- c(selected_idx, next_idx) } # 映射回原始数据的行索引 original_idx <- sapply(selected_idx, function(x) { which(apply(data_mat, 1, function(row) all(row == unique_data[x, ])))[1] }) return(original_idx) }
函数说明
- 维度兼容:支持任意维度的数值型数据框/矩阵
- 重复数据处理:自动去重后采样,再映射回原始数据的行索引
- 分散度保障:通过MaxMin逻辑确保选中样本在空间中尽可能分散
测试示例
# 一维数据测试 one_d <- 1:9 one_d_df <- data.frame(x = one_d) maxmin_sample(one_d_df, 3) # 预期返回类似c(1,5,9)的索引 maxmin_sample(one_d_df, 5) # 预期返回类似c(1,3,5,7,9)的索引 # 多维数据测试 maxmin_sample(df, 10) # 从df中提取10个高分散度行的索引
可选优化方向
- 若数据量极大,可通过分块计算距离提升运行效率
- 若需要固定结果,可在函数开头加入
set.seed()固定随机种子
内容的提问来源于stack exchange,提问作者Laas
相关产品推荐
相关产品推荐

