You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:57:05