Extraer una subcadena de acuerdo con un patrón

136

Supongamos que tengo una lista de cadenas:

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

Ahora espero obtener un vector de cadena que contenga solo las partes después de los dos puntos ":", es decir substring = c(E001,E002,E003).

¿Hay una manera conveniente en R de hacer esto? Utilizando substr?

un pequeño chico
fuente

Respuestas:

239

Aquí hay algunas maneras:

1) sub

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

2) strsplit

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

3) leer.tabla

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

4) subcadena

Esto supone que la segunda parte siempre comienza en el 4 ° carácter (que es el caso en el ejemplo de la pregunta):

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

4a) subcadena / expresión regular

Si el colon no estuviera siempre en una posición conocida, podríamos modificar (4) buscándolo:

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

5) strapplyc

strapplyc devuelve la porción entre paréntesis:

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

6) leer.dcf

Este solo funciona si las subcadenas anteriores al colon son únicas (que están en el ejemplo de la pregunta). También requiere que el separador sea dos puntos (que está en la pregunta). Si se usara un separador diferente, entonces podríamos usarlo subpara reemplazarlo con dos puntos primero. Por ejemplo, si el separador fuera _entoncesstring <- sub("_", ":", string)

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

7) separado

7a) Utilizando tidyr::separatecreamos un marco de datos con dos columnas, una para la parte anterior a los dos puntos y otra para después, y luego extraemos la ú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) Alternativamente separatese puede utilizar para simplemente crear la postcolumna y, a continuación unlisty unnamela trama de datos resultante:

library(dplyr)
library(tidyr)

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

8) recortes Podemos usar trimwspara recortar caracteres de palabras de la izquierda y luego usarlo nuevamente para recortar los dos puntos.

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

Nota

Se stringsupone que la entrada es:

string <- c("G1:E001", "G2:E002", "G3:E003")
G. Grothendieck
fuente
Tenía una variable en una tabla fundida que tenía _como separador e hice dos variables separadas para el prefijo y el sufijo según la respuesta de @Grothendieck: prefix <- sub("_.*", "", variable)y suffix <- sub(".*_", "", variable)
swihart
¡Sería bueno ver un microbenchmarking de esta increíble respuesta!
patl
25

Por ejemplo usando gsubosub

    gsub('.*:(.*)','\\1',string)
    [1] "E001" "E002" "E003"
estudio
fuente
¿Podrías explicar qué son estos? * (* y así sucesivamente, ¿hay exactamente eso? Me está costando recrear esto en un entorno ligeramente diferente ...
Peter Pan el
1
@PeterPan Esto captura y devuelve el grupo de caracteres que aparecen después de los dos puntos. Si las cadenas para unir son más complicadas y desea permanecer en la base R, esto funciona bien.
Clark Fitzgerald
14

Aquí hay otra respuesta simple

gsub("^.*:","", string)
Isaac Ragy
fuente
9

Tarde a la fiesta, pero para la posteridad, el paquete stringr (parte del popular conjunto de paquetes "tidyverse") ahora proporciona funciones con firmas armonizadas para el manejo de cadenas:

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"
CSJCampbell
fuente
2
¿No es esto encontrar el primer número que comienza con una E, en lugar de todo después del colon?
Mark Neal
6

Esto debería hacer:

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

da

[1] "E001" "E002" "E003"
user1981275
fuente
3

Si está utilizando, data.tableentonces tstrsplit()es una opción natural:

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

El paquete de unglue proporciona una alternativa, no se requiere conocimiento sobre expresiones regulares para casos simples, aquí lo haríamos:

# install.packages("unglue")
library(unglue)
string = c("G1:E001", "G2:E002", "G3:E003")
unglue_vec(string,"{x}:{y}", var = "y")
#> [1] "E001" "E002" "E003"

Creado el 06/11/2019 por el paquete reprex (v0.3.0)

Más información: https://github.com/moodymudskipper/unglue/blob/master/README.md

Moody_Mudskipper
fuente