Trích xuất số từ vectơ của chuỗi


101

Tôi có chuỗi như thế này:

years<-c("20 years old", "1 years old")

Tôi chỉ muốn ghi số lượng từ vectơ này. Đầu ra mong đợi là một vectơ:

c(20, 1)

Làm thế nào để tôi làm điều này?

Câu trả lời:


83

Làm thế nào về

# pattern is by finding a set of numbers in the start and capturing them
as.numeric(gsub("([0-9]+).*$", "\\1", years))

hoặc là

# pattern is to just remove _years_old
as.numeric(gsub(" years old", "", years))

hoặc là

# split by space, get the element in first index
as.numeric(sapply(strsplit(years, " "), "[[", 1))

1
Tại sao .*cần thiết? Nếu bạn muốn chúng ngay từ đầu, tại sao không sử dụng ^[[:digit:]]+?
sebastian-c

2
.*là cần thiết vì bạn cần khớp toàn bộ chuỗi. Không có điều đó, không có gì bị loại bỏ. Ngoài ra, lưu ý rằng subcó thể được sử dụng ở đây thay vì gsub.
Matthew Lundberg

12
nếu số không phải ở đầu chuỗi, hãy sử dụng điều này:gsub(".*?([0-9]+).*", "\\1", years)
TMS

Tôi muốn nhận được 27. Tôi không hiểu tại sao, bằng cách thêm các điều kiện (chẳng hạn như thêm một ký tự thoát "-", kết quả nhận được lâu hơn ... gsub(".*?([0-9]+).*?", "\\1", "Jun. 27–30")Kết quả: [1] "2730" gsub(".*?([0-9]+)\\-.*?", "\\1", "Jun. 27–30")Kết quả: [1] "Tháng 6 27 –30 "
Lionel Trebuchon

65

Tôi nghĩ rằng thay thế là một cách gián tiếp để đạt được giải pháp. Nếu bạn muốn truy xuất tất cả các số, tôi khuyên bạn nên gregexpr:

matches <- regmatches(years, gregexpr("[[:digit:]]+", years))
as.numeric(unlist(matches))

Nếu bạn có nhiều kết quả phù hợp trong một chuỗi, điều này sẽ nhận được tất cả chúng. Nếu bạn chỉ quan tâm đến trận đấu đầu tiên, hãy sử dụng regexprthay vì gregexprvà bạn có thể bỏ qua unlist.


1
Tôi không mong đợi điều đó, nhưng giải pháp này chậm hơn bất kỳ giải pháp nào khác, theo một cấp độ lớn.
Matthew Lundberg

@MatthewLundberg cái gregexpr, regexprhay cả hai?
sebastian-c

1
gregexpr. Tôi đã không cố gắng regexprcho đến bây giờ. Sự khác biệt lớn. Sử dụng regexprđặt nó giữa các giải pháp của Andrew và Arun (nhanh thứ hai) trên tập 1e6. Có lẽ cũng thú vị, sử dụng subtrong giải pháp của Andrew không cải thiện tốc độ.
Matthew Lundberg,

Điều này phân chia dựa trên các điểm thập phân. Ví dụ 2,5 trở thành c ('2', '5')
MBorg

65

Cập nhậtextract_numerickhông được dùng nữa, chúng tôi có thể sử dụng parse_numbertừ readrgói.

library(readr)
parse_number(years)

Đây là một tùy chọn khác với extract_numeric

library(tidyr)
extract_numeric(years)
#[1] 20  1

2
Tốt cho ứng dụng này nhưng hãy nhớ parse_numberkhông chơi với số âm. Hãy thử parse_number("–27,633")
Nettle

@Nettle Vâng, đó là đúng và nó sẽ không làm việc nếu có nhiều trường hợp cũng
akrun

3
Lỗi phân tích cú pháp số âm đã được sửa: github.com/tidyverse/readr/issues/308 readr::parse_number("-12,345") # [1] -12345
Russ Hyde

35

Đây là một giải pháp thay thế cho giải pháp đầu tiên của Arun, với một biểu thức chính quy giống Perl đơn giản hơn:

as.numeric(gsub("[^\\d]+", "", years, perl=TRUE))

as.numeric(sub("\\D+","",years)). Nếu có các chữ cái trước và | hoặc sau thìgsub
Onyambu

21

Hoặc đơn giản:

as.numeric(gsub("\\D", "", years))
# [1] 20  1

19

Một stringrgiải pháp pipelined:

library(stringr)
years %>% str_match_all("[0-9]+") %>% unlist %>% as.numeric

Cảm ơn Joe, nhưng câu trả lời này không trích xuất các dấu âm trước các số trong chuỗi.
Miao Cai,

16

Bạn cũng có thể loại bỏ tất cả các chữ cái:

as.numeric(gsub("[[:alpha:]]", "", years))

Tuy nhiên, có vẻ như điều này ít khái quát hơn.


3
Thật kỳ lạ, giải pháp của Andrew đánh bại điều này bằng hệ số 5 trên máy tính của tôi.
Matthew Lundberg

5

Trích xuất số từ bất kỳ chuỗi nào ở vị trí đầu.

x <- gregexpr("^[0-9]+", years)  # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))

Trích xuất số từ bất kỳ chuỗi ĐỘC LẬP của vị trí.

x <- gregexpr("[0-9]+", years)  # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))

4

Chúng tôi cũng có thể sử dụng str_extracttừstringr

years<-c("20 years old", "1 years old")
as.integer(stringr::str_extract(years, "\\d+"))
#[1] 20  1

Nếu có nhiều số trong chuỗi và chúng tôi muốn trích xuất tất cả chúng, chúng tôi có thể sử dụng str_extract_allmà không giống như str_extracttrả về tất cả macthes.

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"


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.