แยกสตริงย่อยตามรูปแบบ


143

สมมติว่าฉันมีรายการสตริง:

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

ตอนนี้ผมหวังว่าจะได้เวกเตอร์ของสตริงที่มีเพียงชิ้นส่วนหลังจากลำไส้ใหญ่ ":" substring = c(E001,E002,E003)คือ

มีวิธีที่สะดวกใน R ในการดำเนินการนี้หรือไม่? ใช้substr?

คำตอบ:


248

วิธีการดังต่อไปนี้:

1) ย่อย

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) สตริงย่อย

สิ่งนี้ถือว่าส่วนที่สองเริ่มต้นที่อักขระที่ 4 เสมอ (ซึ่งเป็นกรณีตัวอย่างในคำถาม):

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

4a) สตริงย่อย / นิพจน์ทั่วไป

หากลำไส้ใหญ่ไม่อยู่ในตำแหน่งที่ทราบเสมอไปเราสามารถแก้ไข (4) โดยค้นหา:

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

5) strapplyc

strapplyc ส่งคืนส่วนในวงเล็บ:

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

6) read.dcf

สิ่งนี้ใช้ได้เฉพาะเมื่อสตริงย่อยก่อนโคลอนไม่ซ้ำกัน (ซึ่งอยู่ในตัวอย่างในคำถาม) นอกจากนี้ยังกำหนดให้ตัวคั่นเป็นโคลอน (ซึ่งอยู่ในคำถาม) หากใช้ตัวคั่นอื่นเราสามารถใช้subเพื่อแทนที่ด้วยเครื่องหมายจุดคู่ก่อน ตัวอย่างเช่นถ้าแยกได้_แล้วstring <- sub("_", ":", string)

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

7) แยกกัน

7a)การใช้tidyr::separateเราสร้าง data frame ที่มีสองคอลัมน์โดยหนึ่งสำหรับส่วนก่อนโคลอนและอีกอันสำหรับ after จากนั้นแยกส่วนหลังออก

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

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

7b)separateสามารถใช้อีกวิธีหนึ่งเพื่อสร้างpostคอลัมน์จากนั้นunlistและunnameกรอบข้อมูลผลลัพธ์:

library(dplyr)
library(tidyr)

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

8) trimwsเราสามารถใช้trimwsเพื่อตัดอักขระคำออกทางซ้ายแล้วใช้อีกครั้งเพื่อตัดลำไส้ใหญ่

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

บันทึก

ข้อมูลที่ป้อนstringจะถือว่า:

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

ฉันมีตัวแปรในตารางหลอมที่มี_ตัวคั่นและสร้างตัวแปรสองตัวแยกกันสำหรับคำนำหน้าและคำต่อท้ายตามคำตอบของ @Grothendieck: prefix <- sub("_.*", "", variable)และ suffix <- sub(".*_", "", variable)
swihart

คงจะดีไม่น้อยหากได้เห็น microbenchmarking ของคำตอบที่น่าทึ่งนี้!
patL

27

ตัวอย่างเช่นการใช้gsubหรือsub

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

คุณช่วยอธิบายสิ่งเหล่านี้ได้ไหม ' * (* ไปเรื่อย ๆ หรือเปล่าฉันมีช่วงเวลาที่ยากลำบากในการสร้างสิ่งนี้ขึ้นมาใหม่ในสภาพแวดล้อมที่แตกต่างกันเล็กน้อย ...
ปีเตอร์แพน

1
@PeterPan สิ่งนี้จะจับและส่งกลับกลุ่มของอักขระที่ปรากฏหลังเครื่องหมายจุดคู่ หากสตริงที่จะจับคู่มีความซับซ้อนมากขึ้นและคุณต้องการอยู่ในฐาน R สิ่งนี้ก็ใช้ได้ดี
Clark Fitzgerald


10

ช่วงสายของงานปาร์ตี้ แต่สำหรับคนรุ่นหลังแพ็คเกจstringr (ส่วนหนึ่งของชุดแพ็คเกจ "tidyverse" ยอดนิยม) มีฟังก์ชันที่มีลายเซ็นที่กลมกลืนกันสำหรับการจัดการสตริง:

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
นี่ไม่ใช่การหาตัวเลขแรกที่ขึ้นต้นด้วย E แทนที่จะเป็นทุกอย่างหลังลำไส้ใหญ่ใช่หรือไม่?
Mark Neal


4

หากคุณกำลังใช้data.tableแล้วtstrsplit()เป็นทางเลือกธรรมชาติ

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

3

unglueแพคเกจให้ทางเลือกที่ไม่มีความรู้เกี่ยวกับการแสดงออกปกติเป็นสิ่งจำเป็นสำหรับกรณีที่เรียบง่ายที่นี่เราจะทำ:

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

สร้างเมื่อ 2019-11-06 โดยแพ็คเกจ reprex (v0.3.0)

ข้อมูลเพิ่มเติม: https://github.com/moodymudskipper/unglue/blob/master/README.md


1

อีกวิธีในการแยกสตริงย่อย

library(stringr)
substring <- str_extract(string, regex("(?<=:).*"))
#[1] "E001" "E002" "E003
  • (?<=:): มองไปข้างหลังลำไส้ใหญ่ ( :)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.