根据模式提取子字符串


136

假设我有一个字符串列表:

string = c("G1:E001", "G2:E002", "G3:E003")

现在,我希望得到一个字符串向量,该向量仅包含冒号“:”之后的部分,即substring = c(E001,E002,E003)

R中有方便的方法吗?使用substr

Answers:


238

以下是几种方法:

1)子

sub(".*:", "", string)
## [1] "E001" "E002" "E003"

2)分裂

sapply(strsplit(string, ":"), "[", 2)
## [1] "E001" "E002" "E003"

3)读取表

read.table(text = string, sep = ":", as.is = TRUE)$V2
## [1] "E001" "E002" "E003"

4)子串

假设第二部分始终从第4个字符开始(在问题示例中就是这种情况):

substring(string, 4)
## [1] "E001" "E002" "E003"

4a)子串/正则表达式

如果结肠并不总是处于已知位置,我们可以通过搜索来修改(4):

substring(string, regexpr(":", string) + 1)

5)绑带

strapplyc 返回括号部分:

library(gsubfn)
strapplyc(string, ":(.*)", simplify = TRUE)
## [1] "E001" "E002" "E003"

6)read.dcf

仅当冒号前面的子字符串是唯一的(在问题的示例中)时,此选项才有效。此外,它还要求分隔符为冒号(这是问题所在)。如果使用了其他分隔符,那么我们可以先用sub冒号代替它。例如,如果隔板是_然后string <- sub("_", ":", string)

c(read.dcf(textConnection(string)))
## [1] "E001" "E002" "E003"

7)分开

7a)使用tidyr::separate我们创建一个包含两列的数据框,一列用于冒号之前的部分,一列用于之后的部分,然后提取后者。

library(dplyr)
library(tidyr)
library(purrr)

DF <- data.frame(string)
DF %>% 
  separate(string, into = c("pre", "post")) %>% 
  pull("post")
## [1] "E001" "E002" "E003"

图7b)可替换地separate,可以使用只创建的post列,然后unlistunname所得到的数据帧:

library(dplyr)
library(tidyr)

DF %>% 
  separate(string, into = c(NA, "post")) %>% 
  unlist %>%
  unname
## [1] "E001" "E002" "E003"

8)修剪我们可以trimws用来修剪左边的文字字符,然后再次使用它修剪冒号。

trimws(trimws(string, "left", "\\w"), "left", ":")
## [1] "E001" "E002" "E003"

注意

string假定输入为:

string <- c("G1:E001", "G2:E002", "G3:E003")

我在一个融化的表中有一个变量,该表_具有分隔符,并根据@Grothendieck答案对前缀和后缀做了两个单独的变量: prefix <- sub("_.*", "", variable)suffix <- sub(".*_", "", variable)
swihart

如果能看到这个惊人答案的微基准测试,那就太好了!
patL

25

例如使用gsubsub

    gsub('.*:(.*)','\\1',string)
    [1] "E001" "E002" "E003"

你能解释这些吗?*(*等等到底在那儿吗?我很难在一个稍微不同的环境中重新创建它…
Peter Pan

1
@PeterPan捕获并返回冒号后面出现的字符组。如果要匹配的字符串更复杂,并且您希望保留在基数R中,则效果很好。
克拉克·菲茨杰拉德


9

聚会晚了,但是为了后代,stringr包(流行的“ tidyverse”包套件的一部分)现在为函数提供了带有统一签名的函数以处理字符串:

string <- c("G1:E001", "G2:E002", "G3:E003")
# match string to keep
stringr::str_extract(string = string, pattern = "E[0-9]+")
# [1] "E001" "E002" "E003"

# replace leading string with ""
stringr::str_remove(string = string, pattern = "^.*:")
# [1] "E001" "E002" "E003"

2
这难道不是找到第一个以E开头的数字,而不是冒号之后的所有数字吗?
Mark Neal

6

应该这样做:

gsub("[A-Z][1-9]:", "", string)

[1] "E001" "E002" "E003"

3

如果您使用的data.tabletstrsplit()是一个自然的选择:

tstrsplit(string, ":")[[2]]
[1] "E001" "E002" "E003"

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.