使用Tidyverse在R中合并数据集:解决重复行、NA与重复列问题
解决犬种数据集合并时的重复列/NA/重复行问题
问题背景
我有两个数据集:breed_traits(包含犬种特征及对应评分)和breed_rank_all(包含2013-2020年美国犬种流行排名),二者均包含Breed列。按Breed列合并时遇到三类问题:
- 排名列出现NA值
- 合并后生成重复行
- 出现
Breed.x与Breed.y重复列
使用merge(x,y, by='row.names', all=TRUE)能获取完整数据,但会保留重复的Breed列,希望通过Tidyverse工具实现单一Breed列且数据正确合并的目标。
数据加载代码
breed_traits <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2022/2022-02-01/breed_traits.csv') trait_description <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2022/2022-02-01/trait_description.csv') breed_rank_all <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2022/2022-02-01/breed_rank.csv')
已尝试的合并方法
- 按行名合并:得到完整数据但存在重复Breed列
breed_total <- merge(breed_traits, breed_rank_all, by = c('row.names') , all=TRUE) breed_total
left_join导致排名列出现大量NA
library(dplyr) breed_traits |> left_join(breed_rank_all, by = c('Breed'))
- 按行名+Breed合并:产生大量重复行
merge(breed_traits, breed_rank_all, by = c('row.names', 'Breed'), all = TRUE)
核心原因
问题本质是两个数据集的Breed列存在名称格式不一致(比如大小写差异、多余空格、品种别名),导致按Breed直接匹配时出现大量不匹配项,进而引发NA、重复行或重复列问题。
Tidyverse解决方案
步骤1:统一Breed列格式
先清理两个数据集的Breed列,消除格式差异:
library(tidyverse) # 定义清理函数:去除首尾空格、统一为标题大小写 clean_breed_col <- function(df) { df |> mutate(Breed = str_squish(str_to_title(Breed))) } # 应用清理函数 breed_traits_clean <- clean_breed_col(breed_traits) breed_rank_clean <- clean_breed_col(breed_rank_all)
步骤2:处理品种别名(关键)
手动映射不一致的品种名称(根据实际数据调整):
breed_rank_clean <- breed_rank_clean |> mutate(Breed = case_when( Breed == "German Shepherd Dog" ~ "German Shepherd", Breed == "Poodle Standard" ~ "Standard Poodle", Breed == "Poodle Miniature" ~ "Miniature Poodle", Breed == "Poodle Toy" ~ "Toy Poodle", TRUE ~ Breed ))
步骤3:完整合并数据集
使用full_join保留两个数据集的所有行,按清理后的Breed列合并:
breed_combined <- breed_traits_clean |> full_join(breed_rank_clean, by = "Breed")
步骤4:验证合并结果
检查合并后的数据质量:
# 查看仅在一个数据集中存在的品种(会有NA) breed_combined |> filter(is.na(Rank2020) | is.na(AffectionateWithFamily)) |> select(Breed, Rank2020, AffectionateWithFamily) # 检查是否存在重复行 breed_combined |> count(Breed) |> filter(n > 1)
内容的提问来源于stack exchange,提问作者Aladar
相关产品推荐
相关产品推荐

