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.