如何对数据框进行子集化:提取最大值周边局部最小值间的行
解决提取最大值周围局部最小值间数据的问题
首先得先把你提供的原始数据整理成正确的两列数据框——你现在的read.table会把所有数值读成一行多列,所以第一步要先把它转换成两列结构,比如第一列叫x,第二列叫y:
# 处理第一个示例数据 dd1 <- read.table(text = " 344 0 350 16 366 11 376 8 380 28 397 55 398 45 400 19 402 30 408 20 415 0 ") dd1 <- as.data.frame(matrix(unlist(dd1), ncol = 2, byrow = TRUE)) colnames(dd1) <- c("x", "y") # 处理第二个示例数据 dd2 <- read.table(text = " 460 0 461 2 463 16 469 33 471 13 473 23 479 38 480 168 481 0") dd2 <- as.data.frame(matrix(unlist(dd2), ncol = 2, byrow = TRUE)) colnames(dd2) <- c("x", "y")
接下来,我们需要一个局部最小值判断函数。这里的局部最小值定义为:某个位置的y值小于它左右相邻的y值(首尾元素仅需单侧小于相邻值即可),用base R实现如下:
find_local_mins <- function(y) { # 初始化逻辑向量,标记每个位置是否为局部最小值 is_local_min <- logical(length(y)) # 处理中间元素:当前值小于左右两侧值 for (i in 2:(length(y)-1)) { is_local_min[i] <- (y[i] < y[i-1]) && (y[i] < y[i+1]) } # 处理第一个元素:小于第二个元素则视为局部最小值 is_local_min[1] <- y[1] < y[2] # 处理最后一个元素:小于倒数第二个元素则视为局部最小值 is_local_min[length(y)] <- y[length(y)] < y[length(y)-1] # 返回所有局部最小值的位置索引 which(is_local_min) }
现在把整个提取流程封装成可复用的函数,这样不管数据维度怎么变都能适用:
extract_around_max <- function(df) { y <- df$y # 找到y列最大值的位置(若有多个最大值,取第一个) max_pos <- which.max(y) # 获取所有局部最小值的位置 local_min_pos <- find_local_mins(y) # 定位最大值左侧最近的局部最小值 left_min_pos <- max(local_min_pos[local_min_pos < max_pos]) # 定位最大值右侧最近的局部最小值 right_min_pos <- min(local_min_pos[local_min_pos > max_pos]) # 提取两个局部最小值之间的所有行(包含两端) result <- df[left_min_pos:right_min_pos, ] return(result) }
测试第一个示例
运行以下代码:
extract_around_max(dd1)
输出结果完全符合你的预期:
x y 4 376 8 5 380 28 6 397 55 7 398 45 8 400 19
测试第二个示例
运行以下代码:
extract_around_max(dd2)
输出结果:
x y 4 469 33 5 471 13 6 473 23 7 479 38 8 480 168 9 481 0
这里最大值168位于第8行,左侧最近的局部最小值是第5行的13(13 < 33且13 < 23),右侧最近的局部最小值是第9行的0,提取范围符合逻辑。
补充说明
- 如果最大值出现在数据首尾,函数会自动适配边界情况;
- 若存在多个相同最大值,
which.max会取第一个,可根据需求修改为处理所有最大值的逻辑; - 局部最小值的定义可微调,比如把“小于”改成“小于等于”,只需修改
find_local_mins函数里的比较符号即可。
内容的提问来源于stack exchange,提问作者user9712506
相关产品推荐
相关产品推荐

