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

PM.*_*PM. 16 r strsplit dplyr

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

下面是一些示例代码和数据,显示我想在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])
Run Code Online (Sandbox Code Playgroud)

我期待strsplit依次对每一行采取行动.

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

Sam*_*rke 17

你可以使用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
Run Code Online (Sandbox Code Playgroud)

正则表达式表示,匹配的一个或多个(+即字符)不是 _(在否定[^ ]),其次是字符串的结尾($).


Phi*_*kle 9

用途dplyr::rowwise:

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

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

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

  • 请注意,这将比典型的`dplyr'慢,因为它无法从向量化操作中受益.仍然,提示+1. (2认同)

vin*_*jor 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
Run Code Online (Sandbox Code Playgroud)


lif*_*oid 6

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])
Run Code Online (Sandbox Code Playgroud)

请参阅https://github.com/tidyverse/stringr/issues/265