ฉันมีสตริงแบบนี้:
years<-c("20 years old", "1 years old")
ฉันต้องการ grep เฉพาะตัวเลขจากเวกเตอร์นี้ ผลลัพธ์ที่คาดหวังคือเวกเตอร์:
c(20, 1)
ฉันจะทำสิ่งนี้ได้อย่างไร?
ฉันมีสตริงแบบนี้:
years<-c("20 years old", "1 years old")
ฉันต้องการ grep เฉพาะตัวเลขจากเวกเตอร์นี้ ผลลัพธ์ที่คาดหวังคือเวกเตอร์:
c(20, 1)
ฉันจะทำสิ่งนี้ได้อย่างไร?
คำตอบ:
เกี่ยวกับ
# pattern is by finding a set of numbers in the start and capturing them
as.numeric(gsub("([0-9]+).*$", "\\1", years))
หรือ
# pattern is to just remove _years_old
as.numeric(gsub(" years old", "", years))
หรือ
# split by space, get the element in first index
as.numeric(sapply(strsplit(years, " "), "[[", 1))
.*
เป็นสิ่งที่จำเป็นเนื่องจากคุณต้องจับคู่สตริงทั้งหมด โดยที่ไม่มีสิ่งใดถูกลบออก นอกจากนี้ทราบว่าสามารถนำมาใช้ที่นี่แทนsub
gsub
gsub(".*?([0-9]+).*", "\\1", years)
gsub(".*?([0-9]+).*?", "\\1", "Jun. 27–30")
ผลลัพธ์: [1] "2730" gsub(".*?([0-9]+)\\-.*?", "\\1", "Jun. 27–30")
ผลลัพธ์: [1] "27 มิ.ย. –30 "
อัปเดต
เนื่องจากextract_numeric
เลิกใช้แล้วเราสามารถใช้parse_number
จากreadr
แพ็คเกจ
library(readr)
parse_number(years)
นี่คืออีกทางเลือกหนึ่งของ extract_numeric
library(tidyr)
extract_numeric(years)
#[1] 20 1
parse_number
อย่าลืมว่าอย่าเล่นกับตัวเลขติดลบ ลอง parse_number("–27,633")
readr::parse_number("-12,345") # [1] -12345
ฉันคิดว่าการทดแทนเป็นวิธีทางอ้อมในการหาทางออก หากคุณต้องการดึงข้อมูลทั้งหมดขอแนะนำgregexpr
:
matches <- regmatches(years, gregexpr("[[:digit:]]+", years))
as.numeric(unlist(matches))
หากคุณมีการแข่งขันหลายรายการในสตริงสิ่งนี้จะได้รับทั้งหมด หากคุณสนใจเฉพาะคู่แรกให้ใช้regexpr
แทนgregexpr
และคุณสามารถข้ามunlist
.
gregexpr
, regexpr
หรือทั้งสอง?
gregexpr
. ผมไม่ได้พยายามregexpr
จนถึงเพียงแค่ตอนนี้ แตกต่างกันมาก การใช้regexpr
ทำให้ระหว่างโซลูชันของ Andrew และ Arun (เร็วที่สุดเป็นอันดับสอง) ในชุด 1e6 บางทีก็น่าสนใจเช่นกันการใช้sub
ในโซลูชันของแอนดรูไม่ช่วยเพิ่มความเร็ว
นี่เป็นทางเลือกสำหรับโซลูชันแรกของ Arun โดยมีนิพจน์ทั่วไปเหมือน Perl ที่ง่ายกว่า:
as.numeric(gsub("[^\\d]+", "", years, perl=TRUE))
as.numeric(sub("\\D+","",years))
. ถ้ามีตัวอักษรก่อนและ | หรือหลังgsub
หรือเพียงแค่:
as.numeric(gsub("\\D", "", years))
# [1] 20 1
stringr
แก้ปัญหาไปป์ไลน์:
library(stringr)
years %>% str_match_all("[0-9]+") %>% unlist %>% as.numeric
คุณสามารถกำจัดตัวอักษรทั้งหมดได้เช่นกัน:
as.numeric(gsub("[[:alpha:]]", "", years))
ดูเหมือนว่าสิ่งนี้จะเข้าใจได้น้อยกว่า
เรายังสามารถใช้str_extract
จากstringr
years<-c("20 years old", "1 years old")
as.integer(stringr::str_extract(years, "\\d+"))
#[1] 20 1
หากมีตัวเลขหลายตัวในสตริงและเราต้องการแยกตัวเลขทั้งหมดออกเราอาจใช้str_extract_all
ซึ่งไม่เหมือนกับการ str_extract
คืนค่าแมคทีฟทั้งหมด
years<-c("20 years old and 21", "1 years old")
stringr::str_extract(years, "\\d+")
#[1] "20" "1"
stringr::str_extract_all(years, "\\d+")
#[[1]]
#[1] "20" "21"
#[[2]]
#[1] "1"
แยกตัวเลขออกจากสตริงใด ๆ ที่ตำแหน่งเริ่มต้น
x <- gregexpr("^[0-9]+", years) # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))
ดึงตัวเลขออกจากสตริง INDEPENDENT ของตำแหน่ง
x <- gregexpr("[0-9]+", years) # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))
หลังจากโพสต์จากGabor Grothendieck โพสต์ที่ r-help mailing list
years<-c("20 years old", "1 years old")
library(gsubfn)
pat <- "[-+.e0-9]*\\d"
sapply(years, function(x) strapply(x, pat, as.numeric)[[1]])
การใช้แพ็คเกจunglueเราสามารถทำได้:
# install.packages("unglue")
library(unglue)
years<-c("20 years old", "1 years old")
unglue_vec(years, "{x} years old", convert = TRUE)
#> [1] 20 1
สร้างเมื่อ 2019-11-06 โดยแพ็คเกจ reprex (v0.3.0)
ข้อมูลเพิ่มเติม: https://github.com/moodymudskipper/unglue/blob/master/README.md
.*
จำเป็น? หากคุณต้องการตั้งแต่เริ่มต้นทำไมไม่ใช้^[[:digit:]]+
?