Ekstrak substring sesuai dengan pola


136

Misalkan saya memiliki daftar string:

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

Sekarang saya berharap untuk mendapatkan vektor string yang hanya berisi bagian setelah titik dua ":", yaitu substring = c(E001,E002,E003).

Apakah ada cara yang nyaman dalam R untuk melakukan ini? Menggunakan substr?

Jawaban:


239

Berikut ini beberapa cara:

1) sub

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

2) strsplit

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

3) baca

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

4) substring

Ini mengasumsikan bagian kedua selalu dimulai pada karakter ke-4 (yang merupakan kasus pada contoh dalam pertanyaan):

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

4a) substring / regex

Jika titik dua tidak selalu dalam posisi yang diketahui, kita dapat memodifikasi (4) dengan mencarinya:

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

5) strapplyc

strapplyc mengembalikan bagian yang di-kurung:

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

6) baca.dcf

Yang ini hanya berfungsi jika substring sebelum titik dua adalah unik (seperti yang ada pada contoh di pertanyaan). Juga mengharuskan pemisah menjadi titik dua (yang ada dalam pertanyaan). Jika pemisah yang berbeda digunakan maka kita bisa menggunakannya subuntuk menggantinya dengan titik dua terlebih dahulu. Sebagai contoh, jika separator itu _kemudianstring <- sub("_", ":", string)

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

7) terpisah

7a) Menggunakan tidyr::separatekita membuat bingkai data dengan dua kolom, satu untuk bagian sebelum titik dua dan satu untuk setelah, dan kemudian mengekstrak yang terakhir.

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

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

7b) Bergantian separatedapat digunakan untuk membuat postkolom dan kemudian unlistdan unnamebingkai data yang dihasilkan:

library(dplyr)
library(tidyr)

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

8) trimws Kita dapat menggunakan trimwsuntuk memotong karakter kata dari kiri dan kemudian menggunakannya lagi untuk memotong titik dua.

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

Catatan

Input stringdiasumsikan:

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

Saya punya variabel dalam tabel lebur yang memiliki _sebagai pemisah dan membuat dua variabel terpisah untuk awalan dan akhiran berdasarkan jawaban @Grothendieck: prefix <- sub("_.*", "", variable)dan suffix <- sub(".*_", "", variable)
swihart

Akan menyenangkan melihat microbenchmarking dari jawaban yang luar biasa ini!
patL

25

Misalnya menggunakan gsubatausub

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

dapatkah Anda menjelaskan apa ini '. * (* dan seterusnya, apakah di sana tepatnya? Saya mengalami kesulitan untuk menciptakan ini dalam pengaturan yang hanya sedikit berbeda ...
Peter Pan

1
@PeterPan Ini menangkap dan mengembalikan kelompok karakter yang muncul setelah titik dua. Jika senar yang cocok lebih rumit dan Anda ingin tetap di pangkalan R ini berfungsi dengan baik.
Clark Fitzgerald


9

Terlambat ke pesta, tetapi untuk anak cucu, paket stringr (bagian dari paket "tidyverse" paket populer) sekarang menyediakan fungsi dengan tanda tangan yang diselaraskan untuk penanganan string:

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
Bukankah ini menemukan angka pertama yang dimulai dengan E, daripada semuanya setelah titik dua?
Mark Neal

6

Ini harus dilakukan:

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

memberi

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

3

Jika Anda menggunakan data.tablemaka itu tstrsplit()adalah pilihan alami:

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.