基于姓氏与名字逐行对比两个DataFrame并筛选交集的实现方法
用dplyr处理DataFrame的匹配与标记需求
我们有如下结构的两个DataFrame:
df1 <- data.frame(lastname = c("Miller", "Smith", "Grey"), firstname = c("John", "Jane", "Hans") ) df2 <- data.frame(lastname =c("Smith", "Grey"), firstname = c("Jane", "Hans") )
注意:df2不一定是df1的子集,也可能包含重复条目。
你需要两种处理方案:一是提取df1中同时出现在两个DataFrame里的所有条目(示例期望输出如下);二是给df1新增标记列,标注姓名是否存在于df2中。以下是基于{dplyr}的实现方法:
示例期望输出(提取共同条目)
res <- data.frame(lastname = c("Smith", "Grey"), firstname = c("Jane", "Hans") )
方案1:提取df1与df2的共同条目
使用inner_join()可以精准匹配两个DataFrame中lastname和firstname完全一致的行。如果df2存在重复条目,可先对df2去重避免结果出现重复:
基础实现(保留所有匹配行,含df2重复导致的重复)
library(dplyr) res_common <- df1 %>% inner_join(df2, by = c("lastname", "firstname"))
去重版实现(得到示例期望输出)
res_common_distinct <- df1 %>% inner_join(distinct(df2), by = c("lastname", "firstname"))
运行后res_common_distinct即为你需要的示例结果。
方案2:给df1添加存在标记列
通过left_join结合mutate,可以给df1新增一列标记该行是否在df2中存在:
方法A:直接关联标记
res_with_flag <- df1 %>% left_join(df2 %>% mutate(in_df2 = TRUE), by = c("lastname", "firstname")) %>% mutate(in_df2 = !is.na(in_df2))
新增的in_df2列中,TRUE表示该姓名在df2中存在,FALSE表示不存在。
方法B:先筛选再标记
如果需要先明确筛选出df1中在df2的行,再合并标记,可使用semi_join:
# 先找出df1中在df2里的行并标记 matched_rows <- df1 %>% semi_join(df2, by = c("lastname", "firstname")) %>% mutate(in_df2 = TRUE) # 合并回原df1并补全标记 res_with_flag <- df1 %>% left_join(matched_rows, by = c("lastname", "firstname")) %>% mutate(in_df2 = ifelse(is.na(in_df2), FALSE, TRUE))
内容的提问来源于stack exchange,提问作者user14692575
相关产品推荐
相关产品推荐

