每 n 个字符拆分字符串新列

Split string every n characters new column

假设我有一个像这样的数据框,带有一个字符串向量,var2

var1  var2
1     abcdefghi 
2     abcdefghijklmnop
3     abc 
4     abcdefghijklmnopqrst

将 var2 每 n 个字符拆分为新列直到每个字符串末尾的最有效方法是什么,

例如,如果每 4 个字符,输出将如下所示:

var1  var2                  new_var1  new_var2 new_var3  new_var4  new_var5
1     abcdefghi             abcd      efgh     i 
2     abcdefghijklmnop      abcd      efgh     ijkl      mnop 
3     abc                   abc
4     abcdefghijklmnopqrst  abcd      efgh     ijkl      mnop      qrst 

stringr 包?使用 "str_split_fixed"

或使用正则表达式:

gsub("(.{4})", "\1 ", "abcdefghi")

根据 var2 的长度创建转到 new_var_n 的新列的能力,例如可以是 10000 个字符。

这是一个带有 data.table 和辅助函数 fixed_split 的选项,我从 this answer 中获取并稍作修改(它使用 tstrsplit 而不是 strsplit).

library(data.table)
fixed_split <- function(text, n) {
  data.table::tstrsplit(text, paste0("(?<=.{",n,"})"), perl=TRUE)
}

定义n,字符数和new_vars,先添加的列数

n <- 4
new_vars <- ceiling(max(nchar(df$var2)) / n)

setDT(df)[, paste0("new_var", seq_len(new_vars)) := fixed_split(var2, n = n)][]
#   var1                 var2 new_var1 new_var2 new_var3 new_var4 new_var5
#1:    1            abcdefghi     abcd     efgh        i     <NA>     <NA>
#2:    2     abcdefghijklmnop     abcd     efgh     ijkl     mnop     <NA>
#3:    3                  abc      abc     <NA>     <NA>     <NA>     <NA>
#4:    4 abcdefghijklmnopqrst     abcd     efgh     ijkl     mnop     qrst

这是使用 strsplitmatrix 强制转换的替代方法

str_split_n <- function(x, n = 4) {
    sapply(x, function(ss) {
        nc <- nchar(as.character(ss))
        apply(matrix(replace(
            rep("", n * ceiling(nc / n)), 1:nc, unlist(strsplit(as.character(ss), ""))),
            nrow = n),
            2,
            paste0, collapse = "")
    })
}

library(dplyr)
library(tidyr)
df %>%
    mutate(tmp = str_split_n(var2)) %>%
    unnest() %>%
    group_by(var1) %>%
    mutate(n = paste0("new_var", 1:n())) %>%
    spread(n, tmp)
## A tibble: 4 x 7
## Groups:   var1 [4]
#   var1 var2                 new_var1 new_var2 new_var3 new_var4 new_var5
#  <int> <fct>                <chr>    <chr>    <chr>    <chr>    <chr>
#1     1 abcdefghi            abcd     efgh     i        NA       NA
#2     2 abcdefghijklmnop     abcd     efgh     ijkl     mnop     NA
#3     3 abc                  abc      NA       NA       NA       NA
#4     4 abcdefghijklmnopqrst abcd     efgh     ijkl     mnop     qrst

对同一个变量使用连续的substr

  library(data.table)
  dff <- fread("var1  var2
1     abcdefghi 
2     abcdefghijklmnop
3     abc 
4     abcdefghijklmnopqrst")

  var2 <- dff[["var2"]]
  for (j in 1:5) {
    set(dff, j = paste0("new_var", j), value = substr(var2, 4*j - 3, 4*j))
  }
  dff
#>    var1                 var2 new_var1 new_var2 new_var3 new_var4 new_var5
#> 1:    1            abcdefghi     abcd     efgh        i                  
#> 2:    2     abcdefghijklmnop     abcd     efgh     ijkl     mnop         
#> 3:    3                  abc      abc                                    
#> 4:    4 abcdefghijklmnopqrst     abcd     efgh     ijkl     mnop     qrst

reprex package (v0.2.0) 创建于 2018-08-05。

或者,您可以在 base R 中尝试 read.fwf。不需要特殊的包:

tmp <- read.fwf(
    textConnection(dtf$var2),
    widths = rep(4, ceiling(max(nchar(dtf$var2) / 4))),
    stringsAsFactors = FALSE)

cbind(dtf, tmp)

#   var1                 var2   V1   V2   V3   V4   V5
# 1    1            abcdefghi abcd efgh    i <NA> <NA>
# 2    2     abcdefghijklmnop abcd efgh ijkl mnop <NA>
# 3    3                  abc  abc <NA> <NA> <NA> <NA>
# 4    4 abcdefghijklmnopqrst abcd efgh ijkl mnop qrst

您可以使用 tidyr::separate :

library(tidyr)
n <- ((max(nchar(df$var2)) - 1) %/% 4) + 1
df %>% separate(var2, into=paste0("new_var", seq(n)), sep=seq(n-1)*4, remove = FALSE)
#   var1                 var2 new_var1 new_var2 new_var3 new_var4 new_var5
# 1    1            abcdefghi     abcd     efgh        i                  
# 2    2     abcdefghijklmnop     abcd     efgh     ijkl     mnop         
# 3    3                  abc      abc                                    
# 4    4 abcdefghijklmnopqrst     abcd     efgh     ijkl     mnop     qrst

我们首先使用整数除法计算我们将拥有多少组,然后我们动态定义新名称并使用 sep 参数中的数值在相关位置拆分。

数据

df <- read.table(text="var1  var2
1     abcdefghi 
2     abcdefghijklmnop
3     abc 
4     abcdefghijklmnopqrst",strin=F,h=T)