Wyodrębnij podciąg zgodnie ze wzorem


143

Załóżmy, że mam listę ciągów:

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

Teraz mam nadzieję, że otrzymam wektor łańcucha zawierający tylko części po dwukropku „:”, tj substring = c(E001,E002,E003).

Czy jest na to wygodny sposób w R? Używasz substr?

Odpowiedzi:


248

Oto kilka sposobów:

1) podp

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

2) strsplit

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

3) przeczytaj. Tabelę

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

4) podciąg

Zakłada się, że druga część zawsze zaczyna się od 4 znaku (tak jest w przykładzie w pytaniu):

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

4a) podciąg / wyrażenie regularne

Gdyby dwukropek nie zawsze znajdował się w znanej pozycji, moglibyśmy zmodyfikować (4), wyszukując go:

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

5) strapplyc

strapplyc zwraca część w nawiasach:

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

6) przeczytaj.dcf

Ten działa tylko wtedy, gdy podciągi przed dwukropkiem są unikalne (tak jak w przykładzie w pytaniu). Wymaga również, aby separatorem był dwukropek (o którym mowa w pytaniu). Gdyby został użyty inny separator, moglibyśmy subnajpierw zastąpić go dwukropkiem. Na przykład, jeśli separator był _wtedystring <- sub("_", ":", string)

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

7) oddzielne

7a) Używając tidyr::separate, tworzymy ramkę danych z dwiema kolumnami, jedną dla części przed dwukropkiem, a drugą dla części po, a następnie wyodrębniamy drugą.

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

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

7b) Alternatywnie separatemożna użyć tylko do utworzenia postkolumny, a następnie unlisti unnamewynikowej ramki danych:

library(dplyr)
library(tidyr)

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

8) trimws Możemy użyć trimwsdo przycięcia znaków słów z lewej strony, a następnie użyć go ponownie do przycięcia dwukropka.

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

Uwaga

stringZakłada się, że dane wejściowe to:

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

Miałem zmienną w stopionej tabeli, która miała _jako separator i utworzyłem dwie oddzielne zmienne dla przedrostka i sufiksu w oparciu o odpowiedź @Grothendieck: prefix <- sub("_.*", "", variable)i suffix <- sub(".*_", "", variable)
swihart

Byłoby miło zobaczyć mikroznak tej niesamowitej odpowiedzi!
patL

27

Na przykład za pomocą gsublubsub

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

czy mógłbyś wyjaśnić, co to jest? * (* i tak dalej, czy dokładnie tam jest? Trudno mi to odtworzyć w tylko trochę innym ustawieniu ...
Peter Pan

1
@PeterPan Przechwytuje i zwraca grupę znaków pojawiających się po dwukropku. Jeśli ciągi do dopasowania są bardziej skomplikowane i chcesz pozostać w bazie R, działa to dobrze.
Clark Fitzgerald


10

Spóźniony na imprezę, ale dla potomnych, pakiet stringr (część popularnego zestawu pakietów „tidyverse”) udostępnia teraz funkcje ze zharmonizowanymi sygnaturami do obsługi ciągów:

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
Czy to nie jest znalezienie pierwszej liczby zaczynającej się od litery E, a nie wszystkiego po dwukropku?
Mark Neal

6

To powinno wystarczyć:

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

daje

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

4

Jeśli używasz data.tablewtedy tstrsplit()jest naturalnym wyborem:

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

3

Unglue pakiet stanowi alternatywę, nie ma wiedzy na temat wyrażeń regularnych jest wymagane w przypadku prostych przypadkach, tutaj chcielibyśmy zrobić:

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

Utworzono 06.11.2019 przez pakiet reprex (v0.3.0)

Więcej informacji: https://github.com/moodymudskipper/unglue/blob/master/README.md


1

Inna metoda wyodrębniania podciągu

library(stringr)
substring <- str_extract(string, regex("(?<=:).*"))
#[1] "E001" "E002" "E003
  • (?<=:): spójrz za okrężnicę ( :)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.