如何合并含特定列不同值的R数据框并处理性别列?
合并共享ID的R数据框并按规则处理性别列
首先修正输入数据的小问题:原代码中id向量长度(4)与其他列(5)不匹配,会触发错误,先修正为长度一致的版本:
# 修正后的输入数据 dfnames1 <- data.frame(id = c(1,2,3,4,5), name1 = c("Helen", "Von", "Erik", "Brook", "Adel"), gender = c("F", "Neutral", "M", "Neutral", "F")) dfnames2 <- data.frame(id = c(1,2,3,4,5), name2 = c("Helen", "Von", "Erik", "Brook", "Adel"), gender2 = c("Neutral", "M", "M", "Uni", "M"))
解决方案
步骤1:合并数据框
通过id主键将两个数据框合并,这里提供基础R和tidyverse两种实现方式:
基础R合并
merged_df <- merge(dfnames1, dfnames2, by = "id")
tidyverse合并(需先加载dplyr)
library(dplyr) merged_df <- inner_join(dfnames1, dfnames2, by = "id")
步骤2:按规则处理性别列
根据需求的规则,我们先将gender2中的"Uni"映射为"M"(匹配预期输出),再编写逻辑处理性别:
基础R实现
# 替换"Uni"为"M" merged_df$gender2[merged_df$gender2 == "Uni"] <- "M" # 定义性别处理函数 process_gender <- function(g1, g2) { non_neutral <- c(g1, g2)[c(g1, g2) != "Neutral"] if (length(non_neutral) == 0) { return("Neutral") } else if (length(unique(non_neutral)) == 1) { return(unique(non_neutral)) } else if (all(c("F", "M") %in% non_neutral)) { return("FM") } } # 应用函数生成最终性别列 merged_df$gender <- mapply(process_gender, merged_df$gender, merged_df$gender2) # 整理成目标格式 dfnames <- merged_df[, c("id", "name1", "gender")] names(dfnames)[2] <- "name"
tidyverse实现
dfnames <- merged_df %>% mutate( # 替换"Uni"为"M" gender2 = ifelse(gender2 == "Uni", "M", gender2), # 按规则生成最终性别 gender = case_when( gender == "Neutral" & gender2 == "Neutral" ~ "Neutral", gender == "Neutral" ~ gender2, gender2 == "Neutral" ~ gender, (gender %in% c("F", "M") & gender2 %in% c("F", "M") & gender != gender2) ~ "FM", TRUE ~ gender ) ) %>% select(id, name = name1, gender)
最终结果
运行上述代码后,得到符合预期的数据框:
> dfnames id name gender 1 1 Helen F 2 2 Von M 3 3 Erik M 4 4 Brook M 5 5 Adel FM
内容的提问来源于stack exchange,提问作者Erik Brole
相关产品推荐
相关产品推荐

