按ID对比DataFrame行,计算匹配得分并提取不匹配项
按ID分组对比组内行并计算匹配得分及提取不匹配项
原始DataFrame
| ID | col1 | Col2 |
|---|---|---|
| AB | 1 | 3 |
| AB | 1 | 3 |
| CD | 2 | 4 |
| CD | 2 | 3 |
| EF | 5 | 10 |
| EF | 1 | 1 |
| GH | 5 | 10 |
| GH | 1 | 10 |
需求说明
按ID分组处理:
- 若某列组内所有值完全相等,
Total列加1分;存在不同值则该列不得分 - 生成不匹配提取列,记录对应列的组内不同值(格式为
值1:值2),无差异则填充Na
期望输出
| ID | col1 | Col2 | Total | mismatch_extract_col1 | mismatch_extract_Col2 |
|---|---|---|---|---|---|
| AB | 1 | 3 | 2 | Na | Na |
| AB | 1 | 3 | 2 | Na | Na |
| CD | 2 | 4 | 1 | Na | 4:3 |
| CD | 2 | 3 | 1 | Na | 4:3 |
| EF | 5 | 10 | 0 | Na | Na |
| EF | 1 | 1 | 0 | Na | Na |
| GH | 5 | 10 | 1 | 5:1 | Na |
| GH | 1 | 10 | 1 | 5:1 | Na |
尝试的代码(未达成需求)
df <- df %>% group_by(ID) %>% mutate(change = ifelse(col1 == lag(col1), 1, 0))
解决方案代码
library(dplyr) df <- df %>% group_by(ID) %>% # 判断每列组内是否全匹配,提取不匹配值 mutate( col1_match = n_distinct(col1) == 1, col2_match = n_distinct(Col2) == 1, # 计算总得分:匹配列的数量 Total = as.integer(col1_match) + as.integer(col2_match), # 生成不匹配提取文本,匹配则填Na mismatch_extract_col1 = ifelse(col1_match, "Na", paste(unique(col1), collapse = ":")), mismatch_extract_Col2 = ifelse(col2_match, "Na", paste(unique(Col2), collapse = ":")) ) %>% # 移除辅助计算列 select(-col1_match, -col2_match) %>% ungroup()
代码说明
n_distinct():统计组内列的唯一值数量,等于1则说明该列所有值一致Total:将匹配标记转换为整数后求和,得到总匹配得分paste(unique(colX), collapse = ":"):把列内的不同值用冒号拼接,生成不匹配提取内容- 最后清理辅助列并取消分组,得到目标结果
内容的提问来源于stack exchange,提问作者simon brocard
相关产品推荐
相关产品推荐

