如何用pivot_longer()处理非关联多组列实现数据拆分?
问题:用
pivot_longer()整理非关联列组的数据集 场景与示例数据
现有一份由Plant和Animal两个数据集合并而来的非规整数据,示例代码如下:
dat <- tibble('Plant_Name'=c('tree','grass','bush','moss','weed','algae'), 'Animal_Name'=c('duck',NA,'horse',NA,NA,'duck'), 'Plant_Info'=c('tall','short','bushy','fuzzy','bad',NA), 'Animal_Info'=c('wet',NA,'fast',NA,NA,'wet'))
目标整洁格式
需要将其转换为如下结构的整洁数据:
# # A tibble: 7 × 3 # Class Name Info # <chr> <chr> <chr> # 1 Animal duck wet # 2 Animal horse fast # 3 Plant bush bushy # 4 Plant grass short # 5 Plant moss fuzzy # 6 Plant tree tall # 7 Plant weed bad
现有方案(扩展性不足)
目前使用unite的方案,新增同类型列时需要修改代码,扩展性较差:
dat %>% unite('Plant',contains('Plant')) %>% unite('Animal',contains('Animal')) %>% pivot_longer(everything(),names_to = 'Class') %>% separate_wider_delim(cols = value,delim = '_',names=c('Name','Info')) %>% mutate(across(c(Name,Info),~ifelse(.x=='NA',NA,.x))) %>% na.omit() %>% arrange(Class,Name) %>% distinct()
更优的pivot_longer()实现方案
利用pivot_longer()的names_pattern参数,通过正则匹配列名的分组规则,直接完成列重组,扩展性更强:
dat %>% pivot_longer( cols = everything(), names_to = c("Class", ".value"), names_pattern = "(.*)_(Name|Info)" ) %>% filter(!is.na(Name)) %>% # 过滤无名称的无效行 arrange(Class, Name) %>% distinct()
方案说明
names_pattern = "(.*)_(Name|Info)":用正则捕获列名的两部分,第一部分(.*)匹配Plant/Animal作为Class,第二部分(Name|Info)匹配属性类型names_to = c("Class", ".value"):指定捕获的第一部分为Class列,第二部分.value表示保留原列名的后缀作为新的列名(即Name和Info)- 后续仅需过滤空名称、排序去重即可得到目标格式,新增
Plant_Type/Animal_Type这类同规则列时,无需修改代码即可适配
内容的提问来源于stack exchange,提问作者S. Robinson
相关产品推荐
相关产品推荐

