Extrair uma substring de acordo com um padrão


136

Suponha que eu tenha uma lista de string:

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

Agora espero obter um vetor de string que contenha apenas as partes após os dois pontos ":", ie substring = c(E001,E002,E003).

Existe uma maneira conveniente no R de fazer isso? Usando substr?

Respostas:


238

Aqui estão algumas maneiras:

1) sub

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

2) strsplit

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

3) read.table

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

4) substring

Isso pressupõe que a segunda parte sempre comece no quarto caractere (que é o caso no exemplo da pergunta):

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

4a) substring / regex

Se os dois pontos nem sempre estivessem em uma posição conhecida, poderíamos modificar (4) procurando por:

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

5) strapplyc

strapplyc retorna a parte entre parênteses:

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

6) read.dcf

Este funciona apenas se as substrings anteriores ao cólon forem únicas (que estão no exemplo da pergunta). Também requer que o separador seja dois pontos (o que está em questão). Se um separador diferente fosse usado, poderíamos subsubstituí-lo por dois pontos primeiro. Por exemplo, se o separador fosse _entãostring <- sub("_", ":", string)

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

7) separado

7a) Usando tidyr::separate, criamos um quadro de dados com duas colunas, uma para a parte antes dos dois pontos e outra para depois, e depois extraímos a última.

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

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

7b) Como alternativa, separatepode ser usado apenas para criar a postcoluna e, em seguida, unliste unnameo quadro de dados resultante:

library(dplyr)
library(tidyr)

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

8) trimws Podemos usar trimwspara aparar caracteres de palavras à esquerda e usá-los novamente para aparar os dois pontos.

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

Nota

A entrada stringé assumida como sendo:

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

Eu tive uma variável em uma mesa derretido que tinha _como um separador e fez duas variáveis separadas para o prefixo e sufixo com base na resposta @Grothendieck: prefix <- sub("_.*", "", variable)e suffix <- sub(".*_", "", variable)
Swihart

Seria bom ver um microbenchmarking desta resposta incrível!
patL 30/01

25

Por exemplo, usando gsubousub

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

você poderia explicar o que é isso? * (* e assim por diante, faça exatamente isso? Estou tendo dificuldade em recriar isso em um ambiente apenas um pouco diferente ... #
6111 Peter Pan Pan

1
@PeterPan Isso captura e retorna o grupo de caracteres que aparecem após os dois pontos. Se as sequências a serem correspondidas forem mais complicadas e você quiser permanecer na base R, isso funcionará bem.
Clark Fitzgerald


9

Tarde para a festa, mas para a posteridade, o pacote stringr (parte do popular conjunto de pacotes "tidyverse") agora fornece funções com assinaturas harmonizadas para manipulação de strings:

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
Não é este achado o primeiro número que começa com um E, em vez de tudo após o cólon?
Mark Neal

6

Isso deve fazer:

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

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

3

Se você estiver usando, data.tableentão tstrsplit()é uma escolha natural:

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.