在R语言中利用条件数据框行对另一数据框计算匹配得分
基于条件数据框计算得分的解决方案
需求说明
现有两个R数据框condition_df和df,需按以下规则计算df每行的得分:
- 以
condition_df的每一行作为判断条件 - 若当前条件的
type未出现在df的type1至type4列中,则检查df中列名等于该条件position的列,若该列当前行的值与条件的subtype匹配,得1分;否则得0分 - 若条件的
type出现在df的type1至type4列中,得0分 - 最终得分为所有条件的得分之和
例如df中ID1的得分为1:前两个条件(type3701、3801)和最后一个条件(type3701)的type均在ID1的type1/type2列中,不计分;第三个条件(type4901)不在ID1的type列中,且position22的列值为D,与subtypeD匹配,得1分,总和为1。
原代码问题分析
你尝试的嵌套循环代码未生效,核心问题有三点:
- 循环覆盖结果:每次循环都会重新生成
cir_score列,最终仅保留最后一个条件的判断结果,而非累加所有条件的得分 - 整列判断而非逐行:
any(across(starts_with("type"))==type)会对整个type列进行判断,返回一个全局逻辑值,导致所有行使用相同的判断结果 - 整列求和而非逐行匹配:
sum(get(position)==subtype)是对整列的匹配结果求和,而非判断当前行的匹配情况
解决方案
方法一:使用dplyr逐行处理(易读性高)
library(dplyr) library(purrr) df <- df %>% rowwise() %>% mutate( # 将当前行的type1-type4转为向量,方便判断type是否存在 type_cols = c(type1, type2, type3, type4), # 遍历每个条件,计算单条件得分后求和 cir_score = sum( map2_dbl( condition_df$type, 1:nrow(condition_df), ~ if (!.x %in% type_cols) { # 匹配当前行对应position列的subtype,转整数(1/0) as.integer(get(as.character(condition_df$position[.y])) == condition_df$subtype[.y]) } else { 0 } ) ) ) %>% ungroup() %>% select(-type_cols) # 移除临时辅助列
方法二:矩阵运算(高效处理大数据)
如果数据量较大,推荐使用向量/矩阵运算替代逐行处理,效率更高:
library(purrr) # 提取df的type1-type4列转为矩阵 type_matrix <- as.matrix(df[, grep("^type", names(df))]) # 生成每个条件下,df每行是否不包含该type的逻辑矩阵 condition_check <- map(condition_df$type, ~ !rowSums(type_matrix == .x)) # 生成每个条件下,df每行对应position列是否匹配subtype的逻辑矩阵 subtype_match <- map2(condition_df$position, condition_df$subtype, ~ df[, as.character(.x)] == .y) # 计算每个条件的得分(逻辑与后转整数),再累加所有条件得分 cir_score <- reduce(map2(condition_check, subtype_match, ~ as.integer(.x & .y)), `+`) # 将得分加入df df$cir_score <- cir_score
验证结果
运行上述代码后,df的cir_score列结果如下:
| id | type1 | type2 | type3 | type4 | 51 | 22 | 13 | 55 | 25 | 16 | cir_score |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 3701 | 3801 | 3901 | 4001 | M | D | E | M | D | E | 1 |
| 2 | 4901 | 4901 | 5001 | 3901 | A | D | G | A | D | G | 1 |
| 3 | 4902 | 4901 | 8901 | 7901 | M | K | E | M | K | E | 2 |
| 4 | 4903 | 5050 | 5050 | 5050 | M | A | E | M | A | E | 3 |
| 5 | 1501 | 6069 | 6069 | 6069 | A | D | G | A | D | G | 2 |
内容的提问来源于stack exchange,提问作者Marwah Al-kaabi
相关产品推荐
相关产品推荐

