Mam taki ciąg:
years<-c("20 years old", "1 years old")
Chciałbym zebrać tylko liczbę liczbową z tego wektora. Oczekiwanym wynikiem jest wektor:
c(20, 1)
Jak mam to zrobić?
Co powiesz na
# pattern is by finding a set of numbers in the start and capturing them
as.numeric(gsub("([0-9]+).*$", "\\1", years))
lub
# pattern is to just remove _years_old
as.numeric(gsub(" years old", "", years))
lub
# split by space, get the element in first index
as.numeric(sapply(strsplit(years, " "), "[[", 1))
.*
konieczne? Jeśli chcesz je mieć na początku, dlaczego nie użyć^[[:digit:]]+
?.*
jest konieczne, ponieważ musisz dopasować cały ciąg. Bez tego nic nie zostanie usunięte. Zwróć też uwagę, żesub
można tego użyć zamiastgsub
.gsub(".*?([0-9]+).*", "\\1", years)
gsub(".*?([0-9]+).*?", "\\1", "Jun. 27–30")
Wynik: [1] „2730”gsub(".*?([0-9]+)\\-.*?", "\\1", "Jun. 27–30")
Wynik: [1] „27 czerwca –30 ”Myślę, że podstawienie jest pośrednim sposobem dojścia do rozwiązania. Jeśli chcesz odzyskać wszystkie numery, polecam
gregexpr
:matches <- regmatches(years, gregexpr("[[:digit:]]+", years)) as.numeric(unlist(matches))
Jeśli masz wiele dopasowań w ciągu, otrzymasz je wszystkie. Jeśli interesuje Cię tylko pierwsze dopasowanie, użyj
regexpr
zamiastgregexpr
i możesz pominąćunlist
.źródło
gregexpr
,regexpr
czy jedno i drugie?gregexpr
. Nie próbowałemregexpr
aż do teraz. Duża różnica. Użycieregexpr
stawia go pomiędzy rozwiązaniami Andrew i Aruna (drugi najszybszy) w zestawie 1e6. Być może również interesujące, użyciesub
w rozwiązaniu Andrew nie poprawia szybkości.Aktualizacja Ponieważ
extract_numeric
jest przestarzała, możemy użyćparse_number
zreadr
pakietu.library(readr) parse_number(years)
Oto inna opcja z
extract_numeric
library(tidyr) extract_numeric(years) #[1] 20 1
źródło
parse_number
że nie gra z liczbami ujemnymi. Spróbujparse_number("–27,633")
readr::parse_number("-12,345") # [1] -12345
Oto alternatywa dla pierwszego rozwiązania Arun, z prostszym wyrażeniem regularnym podobnym do Perla:
as.numeric(gsub("[^\\d]+", "", years, perl=TRUE))
źródło
as.numeric(sub("\\D+","",years))
. Jeśli były listy przed i | lub po, togsub
Lub po prostu:
as.numeric(gsub("\\D", "", years)) # [1] 20 1
źródło
Rozwiązanie
stringr
rurociągowe:library(stringr) years %>% str_match_all("[0-9]+") %>% unlist %>% as.numeric
źródło
Ty też możesz pozbyć się wszystkich liter:
as.numeric(gsub("[[:alpha:]]", "", years))
Prawdopodobnie jest to jednak mniej generalizowalne.
źródło
Wyodrębnij liczby z dowolnego ciągu na pozycji początkowej.
x <- gregexpr("^[0-9]+", years) # Numbers with any number of digits x2 <- as.numeric(unlist(regmatches(years, x)))
Wyodrębnij liczby z dowolnego ciągu NIEZALEŻNEGO od pozycji.
x <- gregexpr("[0-9]+", years) # Numbers with any number of digits x2 <- as.numeric(unlist(regmatches(years, x)))
źródło
Możemy również użyć
str_extract
fromstringr
years<-c("20 years old", "1 years old") as.integer(stringr::str_extract(years, "\\d+")) #[1] 20 1
Jeśli w ciągu znajduje się wiele liczb i chcemy wyodrębnić je wszystkie, możemy użyć funkcji,
str_extract_all
która w przeciwieństwie dostr_extract
zwraca wszystkie makty.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"
źródło
Po wpisie od Gabora Grothendiecka wpis na listę mailingową 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]])
źródło
Odklejając paczkę możemy:
# install.packages("unglue") library(unglue) years<-c("20 years old", "1 years old") unglue_vec(years, "{x} years old", convert = TRUE) #> [1] 20 1
Utworzono 06.11.2019 przez pakiet reprex (v0.3.0)
Więcej informacji: https://github.com/moodymudskipper/unglue/blob/master/README.md
źródło