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

Create new column with dplyr mutate and substring of existing column

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

下面是一些示例代码和数据,显示我想在 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 的一种通用方式来完成您要查找的内容。

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

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

正则表达式表示,匹配 不是 _ 的一个或多个 (+) 个字符(取反 [^ ] ),后跟字符串结尾 ($).

使用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/

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

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

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

# 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