使用dplyr mutate和现有列的子字符串创建新列

时间:2017-02-01 18:10:36

标签: r dplyr strsplit

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

以下是一些示例代码和数据,显示我想在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。你知道为什么会这样吗?失败了,如何实现我的目标?

5 个答案:

答案 0 :(得分:16)

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

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

答案 1 :(得分:9)

没有正则表达式并保持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

答案 2 :(得分:8)

Use dplyr::rowwise:

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

Further alternatives are discussed here:

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

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