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

在R中查找当前行前序行里最接近的小于和大于当前值的数

查找当前行之前最接近的较大ID值

我们有一个包含id列的数据框,需要对每一行,仅从当前行之前的所有行中,找到最接近当前id的大于值(已实现小于值的查找,现需补充大于值逻辑)。示例数据中的max_close_bigger_prior列是预期输出结果:

df <- structure(list(
  row_id = 1:10, 
  id = c(2, 11, 3, 5, 4, 6, 7, 10, 9, 1), 
  min_closest_smaller_prior = c(NA, 2, 2, 3, 3, 5, 6, 7, 7, NA), 
  max_close_bigger_prior = c(NA, NA, 11, 11, 5, 11, 11, 11, 10, 2)
), class = "data.frame", row.names = c(NA, -10L))

已实现的较小值查找代码:

df2 <-
  df %>% mutate(nearest = transform(., close_prev = id[apply(`diag<-`(m <-
                                                                        as.matrix(dist(id)), Inf) / upper.tri(m), 2, which.min)])) %>% as_tibble()

实现较大值查找的两种方法

方法一:逐行筛选+距离计算(直观易理解)

通过逐行提取当前行之前的id,筛选出大于当前id的部分,再从中找距离最近的那个值:

library(dplyr)
library(purrr)

df <- df %>%
  mutate(
    max_close_bigger_prior = pmap_dbl(seq_len(nrow(.)), function(i) {
      prior_ids <- .$id[1:(i-1)]
      # 筛选之前行中大于当前id的元素
      bigger_candidates <- prior_ids[prior_ids > .$id[i]]
      if (length(bigger_candidates) == 0) {
        return(NA_real_)
      }
      # 计算每个候选值与当前id的距离,取最小距离对应的候选值
      bigger_candidates[which.min(abs(bigger_candidates - .$id[i]))]
    })
  )

方法二:维护排序向量+二分查找(高效适合大数据)

如果数据量较大,逐行循环效率偏低,可以维护一个动态排序的已处理id向量,用二分查找快速定位最接近的较大值:

library(dplyr)
library(purrr)

# 初始化空的排序向量,用于存储之前行的id
sorted_prior_ids <- c()

df <- df %>%
  mutate(
    max_close_bigger_prior = map_dbl(id, function(current_id) {
      # 用findInterval找到第一个大于当前id的位置
      pos <- findInterval(current_id, sorted_prior_ids) + 1
      # 判断是否存在大于当前id的元素
      res <- if (pos > length(sorted_prior_ids)) NA_real_ else sorted_prior_ids[pos]
      # 将当前id加入排序向量并重新排序
      sorted_prior_ids <<- sort(c(sorted_prior_ids, current_id))
      res
    })
  )

两种方法都能得到示例中的max_close_bigger_prior列结果,方法二更适合处理行数较多的数据集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 16:35:30