如何将dataframe两列匹配至多列对照表并返回对应结果?
双条件匹配数据框取值问题
现有数据
数据框df1
team_points <- c(1,2,2,2,1) values_rem <- c(15.5,15.3,15.1,15.3,15.2) df1 <- data.frame(team_points, values_rem)
输出:
team_points values_rem 1 1 15.5 2 2 15.3 3 2 15.1 4 2 15.3 5 1 15.2
对照表tbl
values_rem_tbl <- c(15.1, 15.2, 15.3, 15.4, 15.5) team_points_0 <- c(44.2,44.4,44.6,44.8,45) team_points_1 <- c(46.2,46.4,46.6,46.8,47) team_points_2 <- c(48.2,48.4,48.6,48.8,49) tbl <- data.frame(values_rem_tbl, team_points_0, team_points_1, team_points_2)
输出:
values_rem_tbl team_points_0 team_points_1 team_points_2 1 15.1 44.2 46.2 48.2 2 15.2 44.4 46.4 48.4 3 15.3 44.6 46.6 48.6 4 15.4 44.8 46.8 48.8 5 15.5 45.0 47.0 49.0
需求说明
需要将df1每行的team_points和values_rem与tbl匹配:
- 先通过
values_rem匹配tbl中的values_rem_tbl找到对应行 - 再根据
team_points的值,匹配tbl中对应的team_points_X列(X为0-9的数字),提取对应数值作为Result列
期望输出:
team_points values_rem Result 1 1 15.5 47.0 2 2 15.3 48.6 3 2 15.1 48.2 4 2 15.3 48.6 5 1 15.2 46.4
注:实际场景中,tbl的values_rem_tbl范围为0到50(步长0.1),team_points对应列从team_points_0到team_points_9,df1包含其他列但仅需使用上述两列。
解决方案
使用dplyr和tidyr包处理,核心思路是将tbl的宽格式转换为长格式,再通过双条件连接匹配:
library(dplyr) library(tidyr) # 转换tbl为长格式,提取team_points的数字部分 tbl_long <- tbl %>% pivot_longer( cols = starts_with("team_points_"), # 匹配所有team_points_X列 names_to = "team_points", names_pattern = "team_points_(\\d)", # 提取列名中的数字 values_to = "Result" ) %>% mutate(team_points = as.integer(team_points)) # 转换为整数,和df1的列类型一致 # 连接df1和转换后的tbl,匹配条件为values_rem和team_points result_df <- df1 %>% left_join(tbl_long, by = c("values_rem" = "values_rem_tbl", "team_points" = "team_points")) %>% select(team_points, values_rem, Result) # 调整列顺序,保留需要的列 # 查看结果 print(result_df)
运行后输出:
team_points values_rem Result 1 1 15.5 47.0 2 2 15.3 48.6 3 2 15.1 48.2 4 2 15.3 48.6 5 1 15.2 46.4
说明
pivot_longer将宽格式的tbl转为长格式,把每个team_points_X列拆分为team_points(数字)和Result(对应值)两列left_join确保df1的所有行都保留,即使在tbl中没有匹配项(实际场景中应确保所有values_rem和team_points都在tbl中有对应值)- 如果df1有其他列,只需去掉
select语句或调整为需要保留的列即可
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

