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

在R中根据参考数据框区间匹配值并替换为对应ID

问题描述

我在R中有两个dataframe:

  • df1:包含Category、Min、Max、ID列,记录不同类别对应的数值区间及对应ID;
  • df2:包含Name、First、Second列,记录不同名称对应类别的数值。

需求是将df2中各Category列的数值匹配到df1对应类别的Min-Max区间,替换为对应的ID,得到目标输出。


示例数据

先构造两组示例数据方便演示:

# df1:类别区间与ID映射
df1 <- data.frame(
  Category = c("First", "First", "Second", "Second"),
  Min = c(0, 5, 0, 6),
  Max = c(4, 10, 5, 10),
  ID = c("A", "B", "C", "D")
)

# df2:待匹配的数值数据
df2 <- data.frame(
  Name = c("X", "Y", "Z"),
  First = c(3, 7, 2),
  Second = c(4, 8, 6)
)

解决方案(Tidyverse 版本)

利用tidyverse的重塑和连接功能,避免嵌套循环,代码简洁高效:

library(tidyverse)

# 1. 将df2转为长格式,统一处理所有类别列
df2_long <- df2 %>%
  pivot_longer(cols = -Name, names_to = "Category", values_to = "Value")

# 2. 匹配df1的区间规则,筛选出符合条件的ID
matched_data <- df2_long %>%
  left_join(df1, by = "Category") %>%
  filter(Value >= Min & Value <= Max) %>%
  select(Name, Category, ID)

# 3. 转回宽格式,得到最终结果
final_result <- matched_data %>%
  pivot_wider(names_from = Category, values_from = ID)

运行后final_result的输出为:

# A tibble: 3 × 3
  Name  First Second
  <chr> <chr> <chr>
1 X     A     C
2 Y     B     D
3 Z     A     D

解决方案(Data.table 版本)

如果数据量较大,推荐使用data.table的非等连接,性能更优:

library(data.table)

# 转换为data.table格式
setDT(df1)
setDT(df2)

# 1. 转长格式
df2_long <- melt(df2, id.vars = "Name", variable.name = "Category", value.name = "Value")

# 2. 非等连接匹配区间,直接获取对应ID
matched_data <- df2_long[df1, on = .(Category, Value >= Min, Value <= Max), .(Name, Category, ID = i.ID)]

# 3. 转回宽格式
final_result <- dcast(matched_data, Name ~ Category, value.var = "ID")

说明
  • 两种方法都避免了嵌套循环,利用向量化操作提升效率;
  • 如果存在数值不在任何区间的情况,结果中会出现NA,可通过replace_na()函数按需处理;
  • 若df2的类别列不止First和Second,代码无需修改,会自动适配所有非Name列。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 11:25:11