如何比对两个DataFrame的CNPJ与ANO列并给benford列赋值?
解决R中双列匹配并赋值的问题
我来帮你搞定这个双列匹配赋值的需求——你之前用单列匹配的思路没问题,只需要把逻辑扩展到同时匹配CNPJ和ANO两列就行。下面给你两种常用的实现方法,分别基于Base R和tidyverse工具包,都能得到你想要的结果:
先确认数据结构
首先先把你提供的两个DataFrame代码放出来,方便复现和验证:
# caracteristica_receita 数据结构 caracteristica_receita <- structure(list(CNPJ = c(1234, 5678, 91012, 12346, 96385, 87952, 7789, 2535, 4459, 5457), NOME_INSTITUICAO = c("XXXX", "AAAA", "BBBB", "CCCC", "DDDDD", "RRRR", "FFFFF", "GGGGG", "HHHHHH", "IIIIIII"), ano_fundacao = c(1993, 1993, 1994, 1994, 1994, 1994, 1994, 1994, 1994, 1994), ANO = c(2014, 2015, 2014, 2015, 2016, 2014, 2014, 2015, 2016, 2017), benford = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), .Names = c("CNPJ", "NOME_INSTITUICAO", "ano_fundacao", "ANO", "benford"), row.names = c(NA, 10L), class = "data.frame") # coop_receita_anos2d 数据结构 coop_receita_anos2d <- structure(list(CNPJ = c(1234, 5678, 916862, 12346, 96385, 87952, 7789, 2535, 4459, 46868), ANO = c(2014, 2014, 0, 0, 0, 2014, 0, 0, 0, 0)), .Names = c("CNPJ", "ANO"), row.names = c(1L, 3L, 7L, 11L, 15L, 19L, 23L, 27L, 31L, 35L), class = "data.frame")
方法一:Base R 实现
核心思路是把每行的CNPJ和ANO拼接成唯一标识,通过判断这个标识是否存在于另一个数据框的拼接标识中,来确定匹配行:
# 生成两列拼接的匹配键(用下划线分隔避免数值拼接歧义) caracteristica_keys <- with(caracteristica_receita, paste(CNPJ, ANO, sep = "_")) coop_keys <- with(coop_receita_anos2d, paste(CNPJ, ANO, sep = "_")) # 找到匹配的行索引并给benford列赋值1 match_indices <- caracteristica_keys %in% coop_keys caracteristica_receita$benford[match_indices] <- 1
这种方法简单直接,不需要额外安装包,适合习惯Base R的用户。
方法二:tidyverse (dplyr) 实现
如果你平时用dplyr处理数据,用left_join的方式会更直观,逻辑也更清晰:
library(dplyr) caracteristica_receita <- caracteristica_receita %>% # 左连接匹配CNPJ和ANO,给匹配到的行添加标记flag left_join(coop_receita_anos2d %>% mutate(match_flag = 1), by = c("CNPJ", "ANO")) %>% # 根据标记更新benford列:匹配到的设为1,没匹配到的保留原0 mutate(benford = ifelse(!is.na(match_flag), 1, benford)) %>% # 移除临时的标记列 select(-match_flag)
这种方法可读性更强,尤其是处理复杂数据匹配场景时,逻辑不容易出错。
验证结果
运行上面任意一种方法后,你得到的caracteristica_receita就会和你期望的输出完全一致:
# 最终输出结果 structure(list(CNPJ = c(1234, 5678, 91012, 12346, 96385, 87952, 7789, 2535, 4459, 5457), NOME_INSTITUICAO = c("XXXX", "AAAA", "BBBB", "CCCC", "DDDDD", "RRRR", "FFFFF", "GGGGG", "HHHHHH", "IIIIIII"), ano_fundacao = c(1993, 1993, 1994, 1994, 1994, 1994, 1994, 1994, 1994, 1994), ANO = c(2014, 2015, 2014, 2015, 2016, 2014, 2014, 2015, 2016, 2017), benford = c(1, 0, 0, 0, 0, 1, 0, 0, 0, 0)), .Names = c("CNPJ", "NOME_INSTITUICAO", "ano_fundacao", "ANO", "benford"), row.names = c(NA, 10L), class = "data.frame")
内容的提问来源于stack exchange,提问作者RxT
相关产品推荐
相关产品推荐

