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 sub
può 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 regexpr
invece di gregexpr
e puoi saltare il unlist
.
gregexpr
, regexpr
o entrambi?
gregexpr
. Non ci avevo provato regexpr
fino ad ora. Differenza enorme. L'utilizzo lo regexpr
colloca tra le soluzioni di Andrew e Arun (la seconda più veloce) su un set 1e6. Forse anche interessante, l'utilizzo sub
nella soluzione di Andrew non migliora la velocità.
Aggiorna
Poiché extract_numeric
è deprecato, possiamo usare parse_number
from readr
package.
library(readr)
parse_number(years)
Ecco un'altra opzione con extract_numeric
library(tidyr)
extract_numeric(years)
#[1] 20 1
parse_number
non 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_extract
dastringr
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_all
che a differenza di str_extract
restituisce 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:]]+
?