Ho una stringa come questa:
years<-c("20 years old", "1 years old")
Vorrei grep solo il numero numerico da questo vettore. L'output previsto è un vettore:
c(20, 1)
Come procedo a fare questo?
Ho una stringa come questa:
years<-c("20 years old", "1 years old")
Vorrei grep solo il numero numerico da questo vettore. L'output previsto è un vettore:
c(20, 1)
Come procedo a fare questo?
Risposte:
Che ne dite di
# pattern is by finding a set of numbers in the start and capturing them
as.numeric(gsub("([0-9]+).*$", "\\1", years))
o
# pattern is to just remove _years_old
as.numeric(gsub(" years old", "", years))
o
# split by space, get the element in first index
as.numeric(sapply(strsplit(years, " "), "[[", 1))
.*è necessario in quanto è necessario abbinare l'intera stringa. Senza quello, nulla viene rimosso. Inoltre, nota che subpuò essere utilizzato qui invece di gsub.
gsub(".*?([0-9]+).*", "\\1", years)
gsub(".*?([0-9]+).*?", "\\1", "Jun. 27–30")Risultato: [1] "2730" gsub(".*?([0-9]+)\\-.*?", "\\1", "Jun. 27–30")Risultato: [1] "Jun. 27 –30 "
Penso che la sostituzione sia un modo indiretto per arrivare alla soluzione. Se vuoi recuperare tutti i numeri, ti consiglio gregexpr:
matches <- regmatches(years, gregexpr("[[:digit:]]+", years))
as.numeric(unlist(matches))
Se hai più corrispondenze in una stringa, verranno ottenute tutte. Se sei interessato solo alla prima corrispondenza, usa regexprinvece di gregexpre puoi saltare il unlist.
gregexpr, regexpro entrambi?
gregexpr. Non ci avevo provato regexprfino ad ora. Differenza enorme. L'utilizzo lo regexprcolloca tra le soluzioni di Andrew e Arun (la seconda più veloce) su un set 1e6. Forse anche interessante, l'utilizzo subnella soluzione di Andrew non migliora la velocità.
Aggiorna
Poiché extract_numericè deprecato, possiamo usare parse_numberfrom readrpackage.
library(readr)
parse_number(years)
Ecco un'altra opzione con extract_numeric
library(tidyr)
extract_numeric(years)
#[1] 20 1
parse_numbernon si gioca con numeri negativi. Prova parse_number("–27,633")
readr::parse_number("-12,345") # [1] -12345
Potresti sbarazzarti anche di tutte le lettere:
as.numeric(gsub("[[:alpha:]]", "", years))
Probabilmente questo è meno generalizzabile.
Estrae i numeri da qualsiasi stringa nella posizione iniziale.
x <- gregexpr("^[0-9]+", years) # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))
Estrai numeri da qualsiasi stringa INDIPENDENTE dalla posizione.
x <- gregexpr("[0-9]+", years) # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))
Possiamo anche usare str_extractdastringr
years<-c("20 years old", "1 years old")
as.integer(stringr::str_extract(years, "\\d+"))
#[1] 20 1
Se ci sono più numeri nella stringa e vogliamo estrarli tutti, possiamo usare str_extract_allche a differenza di str_extractrestituisce tutti i 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"
Dopo il post di Gabor Grothendieck, posta nella mailing list di 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]])
Usando il pacchetto unglue possiamo fare:
# install.packages("unglue")
library(unglue)
years<-c("20 years old", "1 years old")
unglue_vec(years, "{x} years old", convert = TRUE)
#> [1] 20 1
Creato il 06/11/2019 dal pacchetto reprex (v0.3.0)
Maggiori informazioni: https://github.com/moodymudskipper/unglue/blob/master/README.md
.*necessario? Se li vuoi all'inizio, perché non usarli^[[:digit:]]+?