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.