【问题标题】:Splitting strings into number and string (with missings)将字符串拆分为数字和字符串(有缺失)
【发布时间】:2019-09-06 02:16:53
【问题描述】:

我试图在一列字符串中分隔数字和字符。到目前为止,我一直在使用tidyr::separate 来执行此操作,但遇到“不寻常”情况的错误。

假设我有以下数据

df <- data.frame(c1 = c("5.5K", "2M", "3.1", "M"))

我想获得一个带有列的数据框

data.frame(c2 = c("5.5", "2", "3.1", NA),
c3 = c("K", "M", NA, "M))

到目前为止我一直在使用tidyr::separate

df %>%
separate(c1, into =c("c2", "c3"), sep = "(?<=[0-9])(?=[A-Za-z])")

但这仅适用于前三种情况。我意识到这是因为?&lt;=...?=... 需要正则表达式的存在。如何修改此代码以捕获字母前缺少数字的情况?也曾尝试使用extract 功能,但没有成功。

编辑:我想一种解决方案是将其分解为

df$col2 <- as.numeric(str_extract(df$col1, "[0-9]+"))
df$col3 <- (str_extract(df$col1, "[aA-zZ]+"))

但我很好奇是否有其他方法来处理它。

【问题讨论】:

    标签: r regex string tidyverse


    【解决方案1】:
    extract(df, c1, into =c("c2", "c3"), "([\\.\\d]*)([a-zA-Z]*)")
    #    c2 c3
    # 1 5.5  K
    # 2   2  M
    # 3 3.1   
    # 4      M
    

    seperate这样使用就可以了,不过应该有更优雅的方法..

    df %>% separate(c1, into =c("c2", "c3"), sep = "(?=[A-Za-z])")
    #    c2   c3
    # 1 5.5    K
    # 2   2    M
    # 3 3.1 <NA>
    # 4        M
    

    【讨论】:

    • 谢谢!这是很大的帮助!
    【解决方案2】:

    我们可以使用base R sub分别去除字符和数字,得到不同的列。

    df$c2 <- sub("[A-Za-z]+", "", df$c1)
    df$c3 <- sub("\\d*\\.?\\d*", "", df$c1)
    
    df
    #    c1  c2 c3
    #1 5.5K 5.5  K
    #2   2M   2  M
    #3  3.1 3.1   
    #4    M      M
    

    如果以后不需要,您可以通过 df$c1 &lt;- NULL 删除 c1 列。

    【讨论】:

    • 谢谢!我最终做了非常相似的事情!
    【解决方案3】:

    您还可以使用regex 分组\1\2。这与@Ronak Shah 的回答非常相似并改编自 @Ronak Shah 的回答,但使用了正则表达式分组

    # data
    df <- data.frame(c1 = c("5.5K", "2M", "3.1", "M"))
    
    # keep only numeric
    df$c2 <- sub("(\\d*\\.?\\d*)([A-Za-z]*)", "\\1", df$c1)
    
    # keep only alphabets
    df$c3 <- sub("(\\d*\\.?\\d*)([A-Za-z]*)", "\\2", df$c1)
    df[df == ""] = NA
    
    df
    #>     c1   c2   c3
    #> 1 5.5K  5.5    K
    #> 2   2M    2    M
    #> 3  3.1  3.1 <NA>
    #> 4    M <NA>    M
    

    reprex package (v0.2.1) 于 2019 年 4 月 16 日创建

    【讨论】:

      【解决方案4】:

      我们可以从tidyr使用extract

      library(tidyr)
      extract(df, c1, into = c("c2", "c3"), "^([0-9.]*)([A-Z]*)",
              convert = TRUE, remove = FALSE)
      #    c1  c2 c3
      #1 5.5K 5.5  K
      #2   2M 2.0  M
      #3  3.1 3.1   
      #4    M  NA  M
      

      或者使用read.csv 来自base R

      read.csv(text= sub("^([0-9.]*)", "\\1,", df$c1), 
         header = FALSE, stringsAsFactors = FALSE, col.names = c("c2", "c3"))
      

      【讨论】:

        【解决方案5】:

        你可以使用包脱胶

        df <- data.frame(c1 = c("5.5K", "2M", "3.1", "M"))
        
        library(unglue)
        unglue_unnest(df, c1, "{c2}{c3=\\D*}", convert = TRUE)
        #>    c2 c3
        #> 1 5.5  K
        #> 2 2.0  M
        #> 3 3.1   
        #> 4  NA  M
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-22
          • 1970-01-01
          • 2021-11-29
          相关资源
          最近更新 更多