如何基于一个数据框的条件校验另一个数据框的变量取值?
基于规则校验数据框变量值的解决方案
需求说明
我有两个数据框df1(规则定义表)和df2(待校验数据),需要根据df1中定义的规则,对df2指定变量的取值进行校验,输出每行的校验结果(用T代表TRUE,F代表FALSE)。
规则定义逻辑
df1中每行对应一个校验规则:
var:待校验的目标变量名value:依赖变量需要满足的条件(如==1、!=0)dep:规则依赖的变量名
通用规则逻辑(以var为目标变量,dep为依赖变量,value为依赖条件为例):
- 若依赖变量满足
value指定的条件 → 目标变量校验结果为T - 若依赖变量不满足条件:
- 目标变量为NA → 校验结果为
T - 目标变量不为NA → 校验结果为
F
- 目标变量为NA → 校验结果为
- 若依赖变量和目标变量同时为NA → 校验结果为
T
额外说明:df1中value为NA的行无需处理,可直接移除。实际场景中df2包含多种类型变量(不限于数值型)。
输入数据
df1(规则表)
| var | value | dep |
|---|---|---|
| A | ==1 | E |
| B | ==1 | E |
| C | !=0 | A |
| D | ==2 | G |
| E | NA | NA |
| F | NA | NA |
| G | NA | NA |
df2(待校验数据)
| ID | B | G | A | C | D | E |
|---|---|---|---|---|---|---|
| 1q | 1 | NA | 0 | NA | NA | 2 |
| 2d | 1 | 3 | 0 | 1 | 1 | 2 |
| 4f | NA | NA | 1 | 1 | 1 | 1 |
| 3g | 1 | 2 | 1 | NA | 1 | NA |
| 8j | 2 | 2 | 1 | NA | 1 | NA |
| 5g | NA | NA | NA | 1 | 3 | 3 |
| 9l | 1 | NA | NA | 1 | 2 | NA |
预期输出
| ID | B | A | C | D |
|---|---|---|---|---|
| 1q | F | F | T | T |
| 2d | F | F | F | F |
| 4f | T | T | T | F |
| 3g | F | F | T | T |
| 8j | F | F | T | T |
| 5g | T | T | T | F |
| 9l | T | T | T | F |
R 解决方案
以下代码使用tidyverse工具集实现规则校验,兼容多种变量类型:
library(tidyverse) # 1. 预处理规则表:过滤无效行,拆分运算符和目标值 df1_clean <- df1 %>% filter(!is.na(value)) %>% mutate( # 拆分运算符与值:匹配开头的比较运算符 operator = str_extract(value, "^(==|!=|>|<|>=|<=)"), target_val = str_remove(value, "^(==|!=|>|<|>=|<=)") %>% # 保留原始类型(如字符型直接保留,数值型转换) parse_guess() ) # 2. 定义校验函数:针对单个规则计算每行结果 check_var <- function(var_col, dep_col, operator, target_val) { case_when( # 情况1:依赖变量满足条件 → T eval(parse(text = paste(dep_col, operator, target_val))) ~ TRUE, # 情况3:两者都为NA → T is.na(var_col) & is.na(dep_col) ~ TRUE, # 情况2:依赖不满足,目标为NA → T;否则F is.na(var_col) ~ TRUE, TRUE ~ FALSE ) %>% # 转换为T/F字符 ifelse(., "T", "F") } # 3. 应用所有规则到df2 result_df <- df2 %>% select(ID) %>% bind_cols( map_dfc(1:nrow(df1_clean), function(i) { var_name <- df1_clean$var[i] dep_name <- df1_clean$dep[i] op <- df1_clean$operator[i] val <- df1_clean$target_val[i] check_var( var_col = df2[[var_name]], dep_col = df2[[dep_name]], operator = op, target_val = val ) %>% as_tibble_col(column_name = var_name) }) ) # 输出结果 print(result_df)
代码说明
- 预处理规则表时,通过正则拆分比较运算符和目标值,并用
parse_guess()自动匹配值的类型,保证兼容不同变量类型。 check_var()函数根据规则逻辑分情况判断,使用eval(parse())动态执行比较条件,适配不同的运算符。- 最后通过
map_dfc()批量应用所有规则,整合结果并保留ID列。
内容的提问来源于stack exchange,提问作者Rara
相关产品推荐
相关产品推荐

