【问题标题】:Split string every n characters new column每 n 个字符分割字符串新列
【发布时间】:2026-01-24 13:35:02
【问题描述】:

假设我有一个像这样带有字符串向量 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 的长度(例如,可以是 10000 个字符)创建进入 new_var_n 的新列的能力。

【问题讨论】:

    标签: r substring gsub stringr


    【解决方案1】:

    或者,您可以在 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
    

    【讨论】:

      【解决方案2】:

      这是一个带有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
      

      【讨论】:

      • 你知道我是否有这样的列表 - [1]“a”“b”“c”“d”,我怎样才能将它们组合成“ab”,“cd” .基本上我使用了 str_split("abcd", "") 并卡住了
      • @Hardikgupta 您可以考虑使用fixed_split("abcd", 2)(如上定义)而不是str_split
      【解决方案3】:

      这是使用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
      

      【讨论】:

        【解决方案4】:

        在同一个变量上使用连续的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 年 8 月 5 日创建。

        【讨论】:

          【解决方案5】:

          您可以使用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)
          

          【讨论】:

            最近更新 更多