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

使用R实现不同长度数据框列间值映射与赋值的问题求解

R实现非等值滚动匹配时间列并赋值分数

实现逻辑

你的需求是按id匹配两个数据框,为df1的每个time值匹配df2中第一个大于等于该time值的time2对应的score2,属于按组滚动匹配场景,以下是3种常用实现方案:

前置准备:构造示例数据

# 构造第一个数据框df1
df1 <- structure(list(id = c(4375, 4375, 4375, 4375), time = c(0, 88, 
96, 114)), class = "data.frame", row.names = c(NA, -4L))

# 构造第二个数据框df2
df2 <- structure(list(id2 = c(4375, 4375, 4375, 4375, 4375, 4375, 4375, 
4375, 4375, 4375), time2 = c(0, 2, 87, 88, 94, 97, 101, 104, 
109, 114), score2 = c(0.028, 0.057, 0.057, 0.057, 0.057, 0.057, 
0.057, 0.085, 0.085, 0.085)), class = "data.frame", row.names = c(NA, 
-10L))

方案1:基础R实现(无需额外安装包)

# 先将df2按id和time2升序排序
df2_sorted <- df2[order(df2$id2, df2$time2), ]
# 按id分组匹配对应分数
df1$score <- mapply(function(id, t) {
  # 筛选同id的df2子集
  sub_df2 <- df2_sorted[df2_sorted$id2 == id, ]
  # 找到第一个大于等于t的time2的位置,减1e-9避免浮点精度误差
  idx <- findInterval(t - 1e-9, sub_df2$time2) + 1
  # 超出匹配范围时取最后一个score值
  if(idx > nrow(sub_df2)) idx <- nrow(sub_df2)
  return(sub_df2$score2[idx])
}, df1$id, df1$time)

方案2:data.table实现(效率最高,适合百万级以上大数据量)

library(data.table)
# 转换为data.table格式
setDT(df1)
setDT(df2)
# 设置连接键,roll=-Inf表示匹配最近的>=当前time的time2,mult="first"取第一个匹配结果
setkey(df2, id2, time2)
result <- df2[df1, on = .(id2 = id, time2 >= time), mult = "first"][, .(id = id2, time = time2, score = score2)]

方案3:tidyverse实现(适合tidy生态习惯用户)

library(dplyr)
library(purrr)

result <- df1 %>%
  group_by(id) %>%
  mutate(score = map_dbl(time, ~{
    df2 %>%
      filter(id2 == cur_group()$id, time2 >= .x) %>%
      slice(1) %>%
      pull(score2)
  })) %>%
  ungroup()

注:你给出的期望结果中最后一个time值为116属于笔误,原df1最后一个time为114,按匹配逻辑对应score为0.085,和你期望的score结果一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:36:04