Dizelerin vektörlerinden sayıları çıkarma


103

Bunun gibi bir dizem var:

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

Bu vektörden sadece sayısal sayıyı grep etmek istiyorum. Beklenen çıktı bir vektördür:

c(20, 1)

Bunu nasıl yapacağım?

Yanıtlar:


87

Ne dersin

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

veya

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

veya

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

1
Neden .*gerekli? Onları başlangıçta istiyorsanız, neden kullanmayasınız ^[[:digit:]]+?
sebastian-c

2
.*dizenin tamamını eşleştirmeniz gerektiği için gereklidir. O olmadan hiçbir şey kaldırılmaz. Ayrıca, subbunun yerine burada kullanılabileceğini unutmayın gsub.
Matthew Lundberg

14
sayının dizenin başında olması gerekmiyorsa, şunu kullanın:gsub(".*?([0-9]+).*", "\\1", years)
TMS

27 almak istiyorum. Neden, koşullar ekleyerek (örneğin, çıkış karakterli bir "-" ekleyerek sonuç daha uzun oluyor ... gsub(".*?([0-9]+).*?", "\\1", "Jun. 27–30")Sonuç: [1] "2730" gsub(".*?([0-9]+)\\-.*?", "\\1", "Jun. 27–30")Sonuç: [1] "27 Haz. –30 "
Lionel Trebuchon

66

Bence ikame, çözüme ulaşmanın dolaylı bir yolu. Tüm numaraları geri almak istiyorsanız şunları tavsiye ederim gregexpr:

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

Bir dizede birden fazla eşleşmeniz varsa, bu hepsini alacaktır. Sadece ilk maçla ilgileniyorsanız, regexpryerine kullanın gregexprve atlayabilirsiniz unlist.


1
Bunu beklemiyordum, ancak bu çözüm diğerlerinden herhangi bir büyüklük sırasına göre daha yavaştır.
Matthew Lundberg

@MatthewLundberg gregexpr, regexprya da her ikisi?
sebastian-c

1
gregexpr. regexprŞimdiye kadar denemedim . Büyük farklılık. Kullanmak regexpronu 1e6 setinde Andrew ve Arun'un çözümleri (ikinci en hızlı) arasına koyar. Belki de ilginç, subAndrew'un çözümünde kullanmak hızı iyileştirmiyor.
Matthew Lundberg

Bu, ondalık noktalara göre bölünür. Örneğin 2,5, c ('2', '5') olur
MBorg

66

Güncelleme yana extract_numericitiraz edildi, biz kullanabilirsiniz parse_numbergelen readrpaketin.

library(readr)
parse_number(years)

İşte başka bir seçenek extract_numeric

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

2
Bu uygulama için güzel ancak parse_numbernegatif sayılarla oynamadığını unutmayın . Try parse_number("–27,633")
Nettle

@Nettle Evet, bu doğru ve birden fazla örnek varsa işe yaramayacak
akrun

3
Negatif sayı ayrıştırma hatası düzeltildi: github.com/tidyverse/readr/issues/308 readr::parse_number("-12,345") # [1] -12345
Russ Hyde

35

İşte Arun'un ilk çözümüne daha basit bir Perl benzeri normal ifade ile bir alternatif:

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

as.numeric(sub("\\D+","",years)). Önce ve | veya sonra mektuplar varsa, o zamangsub
Onyambu

21

Ya da sadece:

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

19

Bir stringrardışık çözeltisi:

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

Teşekkürler Joe, ama bu cevap dizedeki sayılardan önceki negatif işaretleri çıkarmıyor.
Miao Cai

16

Siz de tüm harflerden kurtulabilirsiniz:

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

Muhtemelen bu daha az genelleştirilebilir.


3
Garip bir şekilde, Andrew'un çözümü bunu makinemde 5 kat aşıyor.
Matthew Lundberg

5

Başlangıç ​​konumundaki herhangi bir dizeden sayıları ayıklayın.

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

Herhangi bir BAĞIMSIZ dizeden sayıları çıkarın.

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

4

Biz de kullanabilir str_extractdanstringr

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

Dizede birden fazla sayı varsa ve hepsini çıkarmak istiyorsak, tüm macthes'ların str_extract_allaksine olanı kullanabiliriz 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"


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.