Estrai una sottostringa secondo uno schema


136

Supponiamo di avere un elenco di stringhe:

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

Ora spero di ottenere un vettore di stringa che contenga solo le parti dopo i due punti ":", cioè substring = c(E001,E002,E003).

C'è un modo conveniente in R per farlo? Usando substr?

Risposte:


239

Ecco alcuni modi:

1) sott

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) sottostringa

Ciò presuppone che la seconda parte inizi sempre dal 4 ° carattere (come nel caso dell'esempio nella domanda):

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

4a) sottostringa / regex

Se i due punti non fossero sempre in una posizione nota, potremmo modificare (4) cercandolo:

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

5) strapplyc

strapplyc restituisce la parte tra parentesi:

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

6) read.dcf

Questo funziona solo se le sottostringhe prima dei due punti sono uniche (che sono nell'esempio nella domanda). Inoltre richiede che il separatore sia due punti (che è nella domanda). Se fosse usato un separatore diverso, potremmo usarlo subper sostituirlo prima con due punti. Ad esempio, se il separatore fosse _allorastring <- sub("_", ":", string)

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

7) separato

7a) Usando tidyr::separatecreiamo un frame di dati con due colonne, una per la parte prima dei due punti e una per i dopo, quindi estraiamo quest'ultima.

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

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

7b) In alternativa separatepuò essere utilizzato per creare semplicemente la postcolonna e quindi unliste unnameil frame di dati risultante:

library(dplyr)
library(tidyr)

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

8) trimws Possiamo usare trimwsper tagliare i caratteri delle parole a sinistra e poi usarli di nuovo per tagliare i due punti.

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

Nota

Si stringpresume che l'input sia:

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

Avevo una variabile in una tabella fusa che aveva _come separatore e creavo due variabili separate per il prefisso e il suffisso in base alla risposta di @Grothendieck: prefix <- sub("_.*", "", variable)e suffix <- sub(".*_", "", variable)
swihart

Sarebbe bello vedere un microbenching di questa straordinaria risposta!
patL

25

Ad esempio utilizzando gsubosub

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

potresti spiegare cosa sono questi '. * (* e così via esattamente? Sto facendo fatica a ricrearlo in un ambiente solo leggermente diverso ...
Peter Pan,

1
@PeterPan Questo cattura e restituisce il gruppo di caratteri che appare dopo i due punti. Se le stringhe da abbinare sono più complicate e vuoi rimanere nella base R, questo funziona bene.
Clark Fitzgerald,


9

In ritardo per la festa, ma per i posteri, il pacchetto stringr (parte della famosa suite di pacchetti "tidyverse") ora fornisce funzioni con firme armonizzate per la gestione delle stringhe:

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
Non è questo trovare il primo numero che inizia con una E, piuttosto che tutto dopo il colon?
Mark Neal,

6

Questo dovrebbe fare:

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

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

3

Se stai usando, data.tableallora tstrsplit()è una scelta naturale:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.