R语言多列查询辅助表:判断数据框KEY是否含指定食物
解决R语言数据框新增标记列的问题
嘿,我来帮你搞定这个需求!你需要给数据框DF新增TEST列,判断每个KEY在DAY_1到DAY_5期间是否食用过TABLE_AUX里的RICE或BEAN,最终标记为YES/NO。下面是两种简单易用的实现方法:
方法一:Base R 原生实现
这种方法不需要额外安装包,直接用base R的apply函数逐行检查:
首先先构建你的示例数据(方便测试):
# 构建DF数据框 KEY <- c(123,456,789,111,222,333) DAY_1 <- c('RICE','','RICE','','RICE','') DAY_2 <- c('BEAN','','BEAN','','','BEAN') DAY_3 <- c('POTATO','','POTATO','','POTATO','POTATO') DAY_4 <- c('LETTUCE','LETTUCE','','LETTUCE','','LETTUCE') DAY_5 <- c('STEAK','','STEAK','','STEAK','STEAK') DF <- data.frame(KEY,DAY_1,DAY_2,DAY_3,DAY_4,DAY_5, stringsAsFactors = FALSE) # 构建辅助表TABLE_AUX AUX <- c('RICE','BEAN') TABLE_AUX <- data.frame(AUX, stringsAsFactors = FALSE)
然后执行标记逻辑:
# 指定需要检查的日期列 day_columns <- paste0("DAY_", 1:5) # 逐行检查并新增TEST列 DF$TEST <- apply(DF[, day_columns], 1, function(row) { # 判断当前行是否有食物在TABLE_AUX中 if (any(row %in% TABLE_AUX$AUX)) { return("YES") } else { return("NO") } })
方法二:Tidyverse 风格实现
如果你习惯用dplyr和tidyr的话,这种长格式转换的方法更直观:
先加载所需包(如果没安装的话先运行install.packages(c("dplyr", "tidyr"))):
library(dplyr) library(tidyr) # 同样先构建示例数据(和上面一致) KEY <- c(123,456,789,111,222,333) DAY_1 <- c('RICE','','RICE','','RICE','') DAY_2 <- c('BEAN','','BEAN','','','BEAN') DAY_3 <- c('POTATO','','POTATO','','POTATO','POTATO') DAY_4 <- c('LETTUCE','LETTUCE','','LETTUCE','','LETTUCE') DAY_5 <- c('STEAK','','STEAK','','STEAK','STEAK') DF <- data.frame(KEY,DAY_1,DAY_2,DAY_3,DAY_4,DAY_5, stringsAsFactors = FALSE) AUX <- c('RICE','BEAN') TABLE_AUX <- data.frame(AUX, stringsAsFactors = FALSE)
然后执行处理逻辑:
DF <- DF %>% # 将DAY_1到DAY_5转成长格式,方便分组判断 pivot_longer(cols = starts_with("DAY_"), names_to = "day", values_to = "food") %>% # 按KEY分组 group_by(KEY) %>% # 标记是否食用过目标食物 mutate(TEST = if_else(any(food %in% TABLE_AUX$AUX), "YES", "NO")) %>% # 转回宽格式,恢复原数据结构 pivot_wider(names_from = "day", values_from = "food") %>% # 取消分组 ungroup()
验证结果
两种方法运行后,DF的TEST列都会和你期望的一致:
KEY DAY_1 DAY_2 DAY_3 DAY_4 DAY_5 TEST 1 123 RICE BEAN POTATO LETTUCE STEAK YES 2 456 LETTUCE STEAK NO 3 789 RICE BEAN POTATO STEAK YES 4 111 LETTUCE NO 5 222 RICE POTATO STEAK YES 6 333 BEAN POTATO LETTUCE STEAK YES
内容的提问来源于stack exchange,提问作者Bruno Avila
相关产品推荐
相关产品推荐

