在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
相关产品推荐
相关产品推荐

