【问题标题】:Separate character column by Nth character?用第 N 个字符分隔字符列?
【发布时间】:2019-01-29 12:24:18
【问题描述】:

给定一个样本df:

df <- structure(list(test_id = c("123-456789123", "785-525135627", 
"6545646545665456", "988898-65464654646464664", "987-656546464", "666-654564654"
)), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"
))

我想将上面的列分成 2 列:

  1. id 的最后 N 个字符(比如 8 个)
  2. 左前缀

例如给定N = 8:

987-656546464 ---> split to: postfix  prefix
                             56546464 987-6

我已经尝试过单独的功能来做到这一点:

separate(df, col = test_id, into = c("prefix", "postfix"), sep = "(.{8}$)", convert = T)

但它没有给我第二部分。

请指教。

【问题讨论】:

  • 您是否尝试过来自库 stringrstr_sub
  • 试试separate(df, col = test_id, into = c("prefix", "postfix"), sep = 8, convert = TRUE)
  • @Sotos 试过了,但后缀是空列...
  • 哦,我没注意到最后 8个字符。
  • @Sotos 你帮了很多忙。也许你可以解释一下"\\d(?=\\d{8,})" 正则表达式?

标签: r dplyr tidyverse tidyr


【解决方案1】:

请注意,所显示的df 不是data.frame,所以让我们将其称为x。然后将其转换为数据框并使用 separatesep = -8

library(dplyr)
library(tidyr)
x <- df 

x %>% 
  data.frame %>%
  separate(test_id, into = c("pre", "post"), sep = -8)

给予:

               pre     post
1            123-4 56789123
2            785-5 25135627
3         65456465 45665456
4 988898-654646546 46464664
5            987-6 56546464
6            666-6 54564654

【讨论】:

    【解决方案2】:

    更新粗略答案 df2 是 df

    library(tidyverse)
    df2$text_id<-gsub("[-]", "\\1 \\2", df2$test_id)
    df2$test_id
    df2<-df2 %>% 
      mutate(text_id=str_remove_all(df2$text_id,"\\s"),
             text_id=substr(df2$text_id,1,5))
    df2$tesxt_id<-str_replace_all(df2$text_id," ","-")
    df2 %>% 
      separate(test_id,c("pre","post"),sep="\\d(?=\\d{8,})",convert = T) %>% 
      select(tesxt_id,post)
    

    结果:

     tesxt_id     post
      <chr>       <int>
    1 123-4    56789123
    2 785-5    25135627
    3 65456          NA
    4 98889          NA
    5 987-6    56546464
    6 666-6    54564654
    

    试试这个:根据需要重命名列。这匹配前面至少有一个 8 位数字的任何数字。我们使用前瞻 (?=) 来检查在数字 \\d 之前是否有至少 8 位数字 \\d{8,}

    df %>% 
      separate(test_id,c("pre","post"),sep="\\d(?=\\d{8,})",convert = T)
    

    【讨论】:

    • 如果我错了,请纠正我:分开:找到一个数字,在此之后您有 8 个或更多数字。给定 123456789123 它将发现数字 4 是前面跟随 8 个或更多数字的数字。 @nelsongon
    • 是的,它会找到 4。
    • 哦,这是为什么呢?问题是我们失去了一位数。在上面的例子中我们输了 6 个。
    • 在我随问题提供的示例数据集上尝试一下。它是一个字符串而不是一个数字。我想拆分最后 N 个字符
    【解决方案3】:

    这是在不丢失任何数字的情况下解决了我的问题的方法。 请记住,目标是将 8 个字符与末尾分开,然后查看剩下的内容(最后 8 个字符的前缀)。 我需要知道我的数据中最后 8 个字符的唯一前缀是什么。

    df %>%
      as_tibble() %>%
      dplyr::mutate(test_id = str_sub(test_id, end = nchar(test_id) - 8))
    

    【讨论】:

      【解决方案4】:

      不使用额外的包,而是使用sapplystrsplit(显然你应该将东西包装到函数中以获得更清晰的语法):

      >t(sapply(df[,1],function(i,n){sp=unlist(strsplit(i,""));c(postfix=paste0(sp[(length(sp)-n+1):length(sp)],collapse=""),prefix=paste0(sp[1:(length(sp)-n)],collapse=""))},n=8))
                               postfix    prefix
      123-456789123            "56789123" "123-4"
      785-525135627            "25135627" "785-5"
      6545646545665456         "45665456" "65456465"
      988898-65464654646464664 "46464664" "988898-654646546"
      987-656546464            "56546464" "987-6"
      666-654564654            "54564654" "666-6"
      

      【讨论】:

        猜你喜欢
        • 2022-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-17
        • 2018-11-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多