Mengekstrak angka dari vektor string


103

Saya memiliki string seperti ini:

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

Saya hanya ingin grep nomor numerik dari vektor ini. Output yang diharapkan adalah vektor:

c(20, 1)

Bagaimana cara saya melakukan ini?

Jawaban:


87

Bagaimana tentang

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

atau

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

atau

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

1
Mengapa .*perlu? Jika Anda menginginkannya di awal, mengapa tidak digunakan ^[[:digit:]]+?
sebastian-c

2
.*diperlukan karena Anda harus mencocokkan seluruh string. Tanpa itu, tidak ada yang dihapus. Juga, catatan yang subdapat digunakan di sini sebagai pengganti gsub.
Matthew Lundberg

14
jika nomor tersebut tidak harus di awal string, gunakan ini:gsub(".*?([0-9]+).*", "\\1", years)
TMS

Saya ingin mendapatkan 27. Saya tidak mengerti mengapa, dengan menambahkan kondisi (seperti menambahkan "-" yang lolos, hasilnya menjadi lebih panjang ... gsub(".*?([0-9]+).*?", "\\1", "Jun. 27–30")Hasil: [1] "2730" gsub(".*?([0-9]+)\\-.*?", "\\1", "Jun. 27–30")Hasil: [1] "27 Jun. –30 "
Lionel Trebuchon

66

Saya pikir substitusi adalah cara tidak langsung untuk mencapai solusi. Jika Anda ingin mengambil semua nomor, saya sarankan gregexpr:

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

Jika Anda memiliki beberapa kecocokan dalam satu string, ini akan mendapatkan semuanya. Jika Anda hanya tertarik pada pertandingan pertama, gunakan regexprsebagai pengganti gregexprdan Anda dapat melewati unlist.


1
Saya tidak mengharapkannya, tetapi solusi ini lebih lambat daripada yang lain, berdasarkan urutan besarnya.
Matthew Lundberg

@ MatthewLundberg gregexpr, regexpratau keduanya?
sebastian-c

1
gregexpr. Saya belum mencoba regexprsampai sekarang. Perbedaan BESAR. Menggunakan regexprmenempatkannya di antara solusi Andrew dan Arun (tercepat kedua) pada set 1e6. Mungkin juga menarik, menggunakan subsolusi Andrew tidak meningkatkan kecepatan.
Matthew Lundberg

Pembagian ini berdasarkan titik desimal. Misalnya 2.5 menjadi c ('2', '5')
MBorg

66

Perbarui Karena extract_numerictidak digunakan lagi, kita dapat menggunakan parse_numberdari readrpaket.

library(readr)
parse_number(years)

Berikut adalah opsi lain dengan extract_numeric

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

2
Baik untuk aplikasi ini tetapi perlu diingat parse_numberjangan bermain-main dengan angka negatif. Coba parse_number("–27,633")
Nettle

@Nettle Ya, itu benar dan itu tidak akan berfungsi jika ada beberapa contoh juga
akrun

3
Bug penguraian angka negatif telah diperbaiki: github.com/tidyverse/readr/issues/308 readr::parse_number("-12,345") # [1] -12345
Russ Hyde

35

Berikut alternatif solusi pertama Arun, dengan ekspresi reguler mirip Perl yang lebih sederhana:

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

as.numeric(sub("\\D+","",years)). Jika ada surat sebelum dan | atau sesudahnya, makagsub
Onyambu

21

Atau sederhananya:

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

19

Sebuah stringrsolusi pipelined:

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

Terima kasih Joe, tetapi jawaban ini tidak mengekstrak tanda negatif sebelum angka dalam string.
Miao Cai

16

Anda juga bisa menyingkirkan semua huruf:

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

Mungkin ini kurang bisa digeneralisasikan.


3
Anehnya, solusi Andrew mengalahkan ini dengan faktor 5 pada mesin saya.
Matthew Lundberg

5

Ekstrak angka dari string apa pun di posisi awal.

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

Ekstrak angka dari sembarang string INDEPENDEN posisi.

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

4

Kami juga dapat menggunakan str_extractdaristringr

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

Jika ada beberapa angka dalam string dan kami ingin mengekstrak semuanya, kami dapat menggunakan str_extract_allyang tidak seperti str_extractmengembalikan semua 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"

2

Setelah posting dari Gabor Grothendieck posting di milis r-help

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

library(gsubfn)
pat <- "[-+.e0-9]*\\d"
sapply(years, function(x) strapply(x, pat, as.numeric)[[1]])

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.