【问题标题】:Create new column with dplyr mutate and substring of existing column使用 dplyr mutate 和现有列的子字符串创建新列
【发布时间】:2017-06-18 14:38:51
【问题描述】:

我有一个包含一列字符串的数据框,并希望将这些字符串的子字符串提取到一个新列中。

这里是一些示例代码和数据,显示我想在id 列中的最后一个下划线字符之后获取字符串,以创建new_id 列。 id 列条目总是有 2 个下划线字符,它总是我想要的最后一个子字符串。

df = data.frame( id = I(c("abcd_123_ABC","abc_5234_NHYK")), x = c(1.0,2.0) )

require(dplyr)

df = df %>% dplyr::mutate(new_id = strsplit(id, split="_")[[1]][3])

我期待 strsplit 依次作用于每一行。

但是,new_id 列在每一行中仅包含 ABC,而我希望在第 1 行中包含 ABC,在第 2 行中包含 NHYK。您知道为什么会失败以及如何实现我想要的吗?

【问题讨论】:

  • 这是因为您致电strsplit[[1]] 总是抓取列表的第一个元素。
  • 在基础 R 中,就像一点正则表达式魔法一样简单:df$newVar <- sub(".*_([A-Z]+)$", "\\1", df$id)

标签: r dplyr strsplit


【解决方案1】:

这可以通过指定simplify 参数使用str_split 来完成。

Simplify 取消列出拆分字符串并允许使用索引选择元素。在这种总是有 2 个“_”的情况下,我们总是可以取第三个元素。

# Create df
df = data.frame( id = I(c("abcd_123_ABC","abc_5234_NHYK")), x = c(1.0,2.0) )

# Create new_id using dplyr only
df <- df %>% 
  mutate(new_id = str_split(id, "_", simplify = TRUE)[ , 3])

https://github.com/tidyverse/stringr/issues/265

【讨论】:

    【解决方案2】:

    没有正则表达式并保持tidyverse 样式的替代方法是使用tidyr::separate()。请注意,默认情况下这会删除输入列(remove=FALSE 以防止它)。

    ## using your example data
    df = data.frame( id = I(c("abcd_123_ABC","abc_5234_NHYK")), x = c(1.0,2.0) )
    
    ## separate knowing you will have three components
    df %>% separate(id, c("first", "second", "new_id"), sep = "_") %>% select(-first, -second)
    ## returns
      new_id x
    1    ABC 1
    2   NHYK 2
    

    【讨论】:

      【解决方案3】:

      使用dplyr::rowwise:

      df %>% dplyr::rowwise() %>% dplyr::mutate(new_id = strsplit(id, split="_")[[1]][3])
      

      这里讨论了其他替代方案:

      http://www.expressivecode.org/2014/12/17/mutating-using-functions-in-dplyr/

      【讨论】:

      • 请注意,这将比典型的 dplyr 慢,因为它无法从矢量化操作中受益。不过,+1 小费。
      【解决方案4】:

      你可以使用stringr::str_extract:

      library(stringr)
      
       df %>%
         dplyr::mutate(new_id = str_extract(id, "[^_]+$"))
      
      
      #>              id x new_id
      #> 1  abcd_123_ABC 1    ABC
      #> 2 abc_5234_NHYK 2   NHYK
      

      正则表达式表示,匹配一个或多个(+不是_(否定[^ ])的字符,然后是字符串结尾($ )。

      【讨论】:

        【解决方案5】:

        这是一种使用strsplit 的通用方式来完成您正在寻找的事情。

        library(dplyr)
        df = data.frame( id = I(c("abcd_123_ABC","abc_5234_NHYK")), x = c(1.0,2.0) )
        
        temp <- seq(from=3, by=3, length.out = length(df))
        dfn <- df %>% dplyr::mutate(new_id = unlist(strsplit(id, split="_"))[temp])
        
        > dfn
                     id x new_id
        1  abcd_123_ABC 1    ABC
        2 abc_5234_NHYK 2   NHYK
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-23
          • 1970-01-01
          相关资源
          最近更新 更多