将列内的字符串拆分为固定长度的子字符串

时间:2019-07-27 04:14:45

标签: r regex data.table

这是我的模拟代码和数据:

library(data.table)
library(stringr)

data <- data.table(string = c("aaaaaaaaa", "bbbbbb", "ccccccccccccccc", "aaa"))
data[, length := nchar(string)]

data
            string length
1:       aaaaaaaaa      9
2:          bbbbbb      6
3: ccccccccccccccc     15
4:             aaa      3

我需要将“字符串”列拆分为长度为3的子字符串。我希望结果在单独的列中,并且子字符串分开。我试图将for循环与seq结合使用,但是这太慢了,因为我的实际数据超过700万行。

这是我的for循环,在新列中具有所需结果。

for(i in 1:nrow(data)){
  data[i , split := paste(str_sub(string, seq(from = 1, to = length, by = 3),
                          seq(from = 3, to = length, by = 3)), collapse = " - ")]
}

哪一个给我我想要的结果-多么缓慢。

> data
            string length                       split
1:       aaaaaaaaa      9             aaa - aaa - aaa
2:          bbbbbb      6                   bbb - bbb
3: ccccccccccccccc     15 ccc - ccc - ccc - ccc - ccc
4:             aaa      3                         aaa

我正在寻找不使用for循环的解决方案,因此我猜测它必须基于regex

请注意,列string的长度可能有所不同,但始终为3的倍数,并且必须始终分为3组。

非常感谢!

3 个答案:

答案 0 :(得分:2)

我们可以使用gsub

data[, split := trimws(gsub("(...)", "\\1 - ", string), whitespace = '[- ]')][]
#             string length                       split
#1:       aaaaaaaaa      9             aaa - aaa - aaa
#2:          bbbbbb      6                   bbb - bbb
#3: ccccccccccccccc     15 ccc - ccc - ccc - ccc - ccc
#4:             aaa      3                         aaa

答案 1 :(得分:1)

您可以尝试一下。 (?<=^(...)*)(?!^|$)。但是我不知道r语言是否支持它。

This is a demo on regex101.

答案 2 :(得分:1)

我们可以使用strsplit将字符串每3个字符分割一次,然后paste分成一个字符串。

library(data.table)
data[, split := lapply(strsplit(string, "(?<=.{3})", perl=TRUE), 
                paste, collapse = " - ")]

data
#            string                       split
#1:       aaaaaaaaa             aaa - aaa - aaa
#2:          bbbbbb                   bbb - bbb
#3: ccccccccccccccc ccc - ccc - ccc - ccc - ccc
#4:             aaa                         aaa