R语言如何根据矩阵查找匹配值填充DataFrame的COST列
R语言实现跨表重量档位成本匹配方案
你这个需求本质是宽格式矩阵转长表后做键值匹配,比逐行判断加VLOOKUP的方案扩展性好、运行效率高,也不需要硬编码重量判断阈值。
从你给的样例能看出匹配规则:重量向上匹配最近的重量档位(比如1匹配1档,2-3匹配3档,4-5匹配5档),这个逻辑用向量化函数实现即可,不需要写Weight <1.1这类硬判断。
方案1:tidyverse 实现(代码可读性强,适合日常数据处理)
首先载入样例数据:
# 样例数据 Table1 <- structure(list(X = c("SYD", "MEL", "BRIS"), X1 = c(0.29, 0.4, 0.46), X3 = c(0.4, 0.29, 0.87), X5 = c(0.46, 0.85, 0.29)), class = "data.frame", row.names = c(NA, -3L)) Table2 <- structure(list(FROM = c("SYD", "SYD", "SYD", "MEL", "MEL"), Weight = c(1L, 3L, 4L, 1L, 5L), COST = c(0.29, 0.4, 0.46, 0.4, 0.85)), class = "data.frame", row.names = c(NA, -5L))
第一步先把宽格式的Table1转成标准长表,每一行对应「出发地+重量档位+成本」的唯一组合:
library(dplyr) library(tidyr) # 提取所有重量档位并排序 weight_breaks <- sort(as.numeric(gsub("X", "", names(Table1)[-1]))) # 宽转长 Table1_long <- Table1 %>% pivot_longer(cols = -X, names_to = "weight_gear", values_to = "COST") %>% mutate(weight_gear = as.numeric(gsub("X", "", weight_gear))) %>% rename(FROM = X)
第二步给Table2的每条记录匹配对应档位,关联成本:
result <- Table2 %>% select(-COST) %>% # 删掉原有空值/临时值列 mutate( # 向上匹配最近档位 gear_pos = findInterval(Weight, weight_breaks, left.open = TRUE) + 1, match_gear = weight_breaks[gear_pos] ) %>% left_join(Table1_long, by = c("FROM", "match_gear" = "weight_gear")) %>% select(FROM, Weight, COST)
运行结果和你给出的预期输出完全一致:
> result FROM Weight COST 1 SYD 1 0.29 2 SYD 3 0.40 3 SYD 4 0.46 4 MEL 1 0.40 5 MEL 5 0.85
方案2:base R 实现(无需安装第三方包,适合轻量脚本)
如果不想加载tidyverse依赖,用基础R函数也能实现同样效果:
# 提取重量档位 weight_breaks <- sort(as.numeric(gsub("X", "", colnames(Table1)[-1]))) # 转换Table1为长表 Table1_long <- data.frame( FROM = rep(Table1$X, length(weight_breaks)), weight_gear = rep(weight_breaks, each = nrow(Table1)), COST = unlist(Table1[, -1], use.names = FALSE) ) # 匹配档位 Table2$gear_pos <- findInterval(Table2$Weight, weight_breaks, left.open = TRUE) + 1 Table2$match_gear <- weight_breaks[Table2$gear_pos] # 关联匹配成本 Table2$COST <- Table1_long$COST[match( paste(Table2$FROM, Table2$match_gear), paste(Table1_long$FROM, Table1_long$weight_gear) )] # 输出结果 result <- Table2[, c("FROM", "Weight", "COST")]
方案优势
- 无硬编码阈值:后续新增/修改重量档位,只需要调整Table1的列即可,不需要修改匹配逻辑代码
- 运行效率高:全向量化操作,处理十万级以上数据比逐行VLOOKUP/循环快10~100倍
- 规则调整灵活:如果需要改成向下匹配、自定义区间,只需要调整
findInterval的参数即可,不需要重构代码
内容的提问来源于stack exchange,提问作者Raul Ravi
相关产品推荐
相关产品推荐

