我有一个包含一列字符串的数据框,并希望将这些字符串的子字符串提取到一个新列中.
下面是一些示例代码和数据,显示我想在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)
正则表达式表示,匹配的一个或多个(+
即字符)不是 _
(在否定[^ ]
),其次是字符串的结尾($
).
用途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/
没有正则表达式并保持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)
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