在R语言中基于查找表按多条件匹配并添加唯一ID
问题描述
现有一个包含大量数据的data.frame(df)和一个参考用的data.frame(lookup),需要根据lookup中的三个条件,为df添加对应的unique_id。
示例数据
目标数据集df
df <- data.frame(fruit = c("mango", "strawberry", "strawberry", "apple", "mango"), size = c(34, 17, 29, 10, 1), var_x = c("X4", "X1", "X1a", "X1", "X1b") )
数据预览:
fruit size var_x 1 mango 34 X4 2 strawberry 17 X1 3 strawberry 29 X1a 4 apple 10 X1 5 mango 1 X1b
参考查找表lookup
lookup <- data.frame(unique_id = LETTERS[1:7], fruit = c("apple", "apple", "strawberry", "mango", "mango", "mango", "mango"), size = c("1:9", "1:9", "10:40", "1:100", "1:9", "1:9", "10:40"), var_x = c("c('X1', 'X1a', 'X1b')", "X3", "c('X1', 'X1a', 'X1b')", "c('X1', 'X1a', 'X1b')", "X2", "X3","c('X1', 'X4')") )
数据预览:
unique_id fruit size var_x 1 A apple 1:9 c('X1', 'X1a', 'X1b') 2 B apple 1:9 X3 3 C strawberry 10:40 c('X1', 'X1a', 'X1b') 4 D mango 1:100 c('X1', 'X1a', 'X1b') 5 E mango 1:9 X2 6 F mango 1:9 X3 7 G mango 10:40 c('X1', 'X4')
匹配规则与预期输出
匹配需同时满足三个条件:
df与lookup的fruit字段完全匹配df$size落在lookup$size指定的数值范围内df$var_x属于lookup$var_x指定的选项集合(支持单个或多个选项)
匹配后为df添加对应unique_id,修正后的正确预期输出:
unique_id fruit size var_x 1 G mango 34 X4 2 C strawberry 17 X1 3 C strawberry 29 X1a 4 <NA> apple 10 X1 5 D mango 1 X1b
解决方案
核心是解析lookup中的范围表达式和多选项表达式,再逐行匹配条件,实现代码如下:
# 加载依赖包 library(dplyr) library(purrr) # 预处理lookup表:解析范围和选项列表 lookup_processed <- lookup %>% mutate( # 将size范围拆分为最小值和最大值 size_min = as.integer(sub(":(.*)", "", size)), size_max = as.integer(sub("(.*):", "", size)), # 解析var_x的表达式为字符向量 var_x_list = map(var_x, ~eval(parse(text = .x))) ) # 定义单条数据的匹配函数 match_unique_id <- function(row_data) { # 筛选符合所有条件的lookup记录 matched_rows <- lookup_processed %>% filter( fruit == row_data$fruit, row_data$size >= size_min, row_data$size <= size_max, row_data$var_x %in% var_x_list[[1]] ) # 返回第一个匹配的unique_id,无匹配则返回NA if (nrow(matched_rows) > 0) matched_rows$unique_id[1] else NA_character_ } # 应用匹配逻辑到df的每一行 result_df <- df %>% rowwise() %>% mutate(unique_id = match_unique_id(cur_data())) %>% ungroup() %>% select(unique_id, everything()) # 查看最终结果 print(result_df)
代码说明
预处理lookup表:
- 拆分
size字段的范围字符串为数值型的size_min和size_max,简化范围判断逻辑 - 用
map结合eval(parse())解析var_x中的表达式,将单个值或多值字符串转换为可直接判断的字符向量
- 拆分
匹配函数:
- 对
df的每一行,筛选出同时满足三个匹配条件的lookup记录 - 返回第一个匹配的
unique_id,无匹配结果时返回NA
- 对
批量处理数据集:
- 使用
rowwise()逐行处理df,调用匹配函数生成unique_id - 调整列顺序,将
unique_id放在数据集最前端
- 使用
内容的提问来源于stack exchange,提问作者afleishman
相关产品推荐
相关产品推荐

