R语言:如何拆分数据框字符列并修正NA分布,保留目标列结构?
问题:如何将tibble中按日期分组的逗号分隔列拆分为对齐的多列?
原始数据
首先构造示例tibble:
library(tidyverse) date = c(rep(as.Date("2022/1/1"),3), rep(as.Date("2022/1/2"),3), rep(as.Date("2022/1/3"),3)) var1 = c(rep("cat",3),rep("cat,Mother,bike,pasta",3),rep("dog,bird",3)) a = seq(1,9,1) b = seq(10,18,1) c = seq(19,27,1) df = tibble(date,a,b,c,var1)
生成的数据如下:
# A tibble: 9 × 5 date a b c var1 <date> <dbl> <dbl> <dbl> <chr> 1 2022-01-01 1 10 19 cat 2 2022-01-01 2 11 20 cat 3 2022-01-01 3 12 21 cat 4 2022-01-02 4 13 22 cat,Mother,bike,pasta 5 2022-01-02 5 14 23 cat,Mother,bike,pasta 6 2022-01-02 6 15 24 cat,Mother,bike,pasta 7 2022-01-03 7 16 25 dog,bird 8 2022-01-03 8 17 26 dog,bird 9 2022-01-03 9 18 27 dog,bird
当前错误的尝试及结果
尝试使用separate_rows和pivot_wider拆分列,但得到错位的NA:
df %>% separate_rows(var1) %>% group_by(date) %>% mutate(id = row_number()) %>% pivot_wider(names_from = id, values_from = var1)
错误结果:
# A tibble: 9 × 16 # Groups: date [3] date a b c `1` `2` `3` `4` `5` `6` `7` `8` `9` `10` `11` `12` <date> <dbl> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> 1 2022-01-01 1 10 19 cat NA NA NA NA NA NA NA NA NA NA NA 2 2022-01-01 2 11 20 NA cat NA NA NA NA NA NA NA NA NA NA 3 2022-01-01 3 12 21 NA NA cat NA NA NA NA NA NA NA NA NA 4 2022-01-02 4 13 22 cat Mother bike pasta NA NA NA NA NA NA NA NA 5 2022-01-02 5 14 23 NA NA NA NA cat Mother bike pasta NA NA NA NA 6 2022-01-02 6 15 24 NA NA NA NA NA NA NA NA cat Mother bike pasta 7 2022-01-03 7 16 25 dog bird NA NA NA NA NA NA NA NA NA NA 8 2022-01-03 8 17 26 NA NA dog bird NA NA NA NA NA NA NA NA 9 2022-01-03 9 18 27 NA NA NA NA dog bird NA NA NA NA NA NA
期望的目标格式
需要得到拆分后同日期分组内所有行的拆分列对齐的结果:
| date | a | b | c | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|---|---|
| 2022-01-01 | 1 | 10 | 19 | cat | NA | NA | NA |
| 2022-01-01 | 2 | 11 | 20 | cat | NA | NA | NA |
| 2022-01-01 | 3 | 12 | 21 | cat | NA | NA | NA |
| 2022-01-02 | 4 | 13 | 22 | cat | Mother | bike | pasta |
| 2022-01-02 | 5 | 14 | 23 | cat | Mother | bike | pasta |
| 2022-01-02 | 6 | 15 | 24 | cat | Mother | bike | pasta |
| 2022-01-03 | 7 | 16 | 25 | dog | bird | NA | NA |
| 2022-01-03 | 8 | 17 | 26 | dog | bird | NA | NA |
| 2022-01-03 | 9 | 18 | 27 | dog | bird | NA | NA |
解决方案
方法一:使用separate_wider_delim(推荐)
separate_wider_delim是tidyverse中专门用于拆分分隔列的函数,直接指定分隔符即可自动拆分并对齐列,无需额外分组:
df %>% separate_wider_delim(var1, delim = ",", names_sep = "", too_few = "align_start")
参数说明:
delim = ",":指定拆分的分隔符为逗号names_sep = "":拆分后的列名直接用序号(如1、2),无需前缀too_few = "align_start":当某行拆分后的元素数量少于最大列数时,从开头对齐,剩余列补NA
方法二:修正separate_rows+pivot_wider的逻辑
之前的错误在于按date分组生成序号,导致序号跨原始行递增。正确的做法是先给每个原始行分配唯一id,再按该id生成拆分元素的序号:
df %>% mutate(row_id = row_number()) %>% # 给每个原始行加唯一标识 separate_rows(var1) %>% group_by(row_id) %>% # 按原始行分组生成拆分元素的序号 mutate(id = row_number()) %>% pivot_wider(names_from = id, values_from = var1) %>% select(-row_id) # 移除临时的行标识
两种方法都能得到你需要的对齐格式。
内容的提问来源于stack exchange,提问作者Homer Jay Simpson
相关产品推荐
相关产品推荐

