当行间的片段数不同时,将字符串拆分为三列

Split character string into three columns when number of pieces differs between rows

提问人:Sam 提问时间:5/15/2020 更新时间:5/16/2020 访问量:130

问:

我有一个类似于以下 reprex 的数据帧:

test <- data.frame(
  age = c("6 hours", "2 days, 4 hours", "1 months3 days, 7 hours")
)

不幸的是,正如您在第 3 行中看到的那样,字符串的三部分并非都用逗号分隔。

我的预期输出如下:

                        age agem aged ageh
1                   6 hours   NA   NA   6
2           2 days, 4 hours   NA    2   4
3 1 months3 days, 7 hours      1    3   7

我试过这样使用dplyr::separate

new_test <- test %>%
  separate(age, c("agem", "ageh", "aged"), sep = "[^[\\d]]+", convert = TRUE,
           remove = FALSE, fill = "left")

这对于只有“小时”的条目非常有效,但如果有“天和小时”或“月、天和小时”,则输出的顺序是错误的。

任何帮助将不胜感激。

r

评论


答:

3赞 Rui Barradas 5/15/2020 #1

首先,在字母字符和数字之间没有分隔符的地方添加分隔符。然后进入列。tidyr::separate

library(tidyverse)

test %>%
  mutate(age = gsub("([[:alpha:]])([[:digit:]])", "\\1, \\2", age)) %>%
  separate(age, into = c('agem', 'aged', 'ageh'), 
           sep = ', ',
           convert = TRUE,
           remove = FALSE, fill = "left") %>%
  mutate_at(vars(matches('age[[:alpha:]]')), function(x) as.numeric(gsub('[^[:digit:]]', '', x)))
#                        age agem aged ageh
#1                   6 hours   NA   NA    6
#2           2 days, 4 hours   NA    2    4
#3 1 months, 3 days, 7 hours    1    3    7

评论

0赞 Shan R 5/15/2020
很棒的解决方案。@Sam,如果您需要删除新列的文本部分,一种方法是使用 Library Readr 中的parse_number。
0赞 Chris Ruehlemann 5/16/2020
文本部分不包括在预期成果中
3赞 Chris Ruehlemann 5/16/2020 #2

您可以使用包和积极的展望:str_extractstringr(?= ...)

test$agem <- str_extract(test$age, "\\d+(?=\\smonth)")
test$aged <- str_extract(test$age, "\\d+(?=\\sday)")
test$ageh <- str_extract(test$age, "\\d+(?=\\shour)")

结果:

test
                      age agem aged ageh
1                 6 hours <NA> <NA>    6
2         2 days, 4 hours <NA>    2    4
3 1 months3 days, 7 hours    1    3    7

评论

0赞 Sam 9/17/2020
一个非常简单而优雅的解决方案,效果很好,谢谢。对于延迟,我深表歉意,但我现在已将其标记为公认的答案,因为尽管两个发布的解决方案都有效,但这是我使用的解决方案,也是最简洁的解决方案。