Trích xuất một chuỗi con theo một mẫu


136

Giả sử tôi có một danh sách các chuỗi:

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

Bây giờ tôi hy vọng sẽ có được một vectơ chuỗi chỉ chứa các phần sau dấu hai chấm ":", tức là substring = c(E001,E002,E003).

Có một cách thuận tiện trong R để làm điều này? Sử dụng substr?

Câu trả lời:


237

Dưới đây là một vài cách:

1) phụ

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

2) strsplit

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

3) có thể đọc được

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

4) chuỗi con

Giả định phần thứ hai này luôn bắt đầu ở ký tự thứ 4 (đó là trường hợp trong ví dụ trong câu hỏi):

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

4a) chuỗi con / regex

Nếu dấu hai chấm không phải luôn luôn ở một vị trí đã biết, chúng ta có thể sửa đổi (4) bằng cách tìm kiếm nó:

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

5)

strapplyc trả về phần ngoặc đơn:

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

6) đọc.dcf

Điều này chỉ hoạt động nếu các chuỗi con trước dấu hai chấm là duy nhất (mà chúng nằm trong ví dụ trong câu hỏi). Ngoài ra, nó yêu cầu dấu phân cách là dấu hai chấm (mà nó nằm trong câu hỏi). Nếu một dấu phân cách khác được sử dụng thì chúng ta có thể sử dụng subđể thay thế nó bằng dấu hai chấm trước. Ví dụ: nếu dấu phân cách _thìstring <- sub("_", ":", string)

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

7) riêng biệt

7a) Sử dụng tidyr::separatechúng tôi tạo một khung dữ liệu với hai cột, một cho phần trước dấu hai chấm và một cho phần sau, sau đó trích xuất phần sau.

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

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

7b) Luân phiên separatecó thể được sử dụng để chỉ tạo postcột và sau đó unlistunnamekhung dữ liệu kết quả:

library(dplyr)
library(tidyr)

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

8) trimws Chúng ta có thể sử dụng trimwsđể cắt các ký tự từ bên trái và sau đó sử dụng nó một lần nữa để cắt dấu hai chấm.

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

Ghi chú

Đầu vào stringđược giả định là:

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

Tôi đã có một biến trong một bảng tan chảy có _dấu phân cách và tạo hai biến riêng biệt cho tiền tố và hậu tố dựa trên câu trả lời @Grothendieck: prefix <- sub("_.*", "", variable)suffix <- sub(".*_", "", variable)
swihart

Thật tuyệt khi thấy một microbenchmarking của câu trả lời tuyệt vời này!
patL

25

Ví dụ: sử dụng gsubhoặcsub

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

bạn có thể khám phá những gì '. * (* và cứ thế làm chính xác? Tôi đang gặp khó khăn trong việc tái tạo điều này trong một khung cảnh chỉ hơi khác một chút ...
Peter Pan

1
@PeterPan Điều này chụp và trả về nhóm các ký tự xuất hiện sau dấu hai chấm. Nếu các chuỗi phù hợp phức tạp hơn và bạn muốn ở lại cơ sở R thì điều này hoạt động tốt.
Clark Fitzgerald

14

Đây là một câu trả lời đơn giản

gsub("^.*:","", string)

9

Đến bữa tiệc muộn, nhưng đối với hậu thế, gói Stringr (một phần của bộ gói "tidyverse" phổ biến) hiện cung cấp các hàm với chữ ký hài hòa để xử lý chuỗi:

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
Đây không phải là tìm số đầu tiên bắt đầu bằng E, chứ không phải là tất cả mọi thứ sau dấu hai chấm?
Đánh dấu


3

Nếu bạn đang sử dụng data.tablethì đó tstrsplit()là một lựa chọn tự nhiên:

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

3

Các unglue gói cung cấp một sự thay thế, không có kiến thức về biểu thức thông thường là cần thiết cho trường hợp đơn giản, ở đây chúng tôi muốn làm:

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

Được tạo vào ngày 2019-11-06 bởi gói reprex (v0.3.0)

Thông tin thêm: https://github.com/moodymudskipper/unglue/blob/master/README.md

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.