Eu tenho uma string assim:
years<-c("20 years old", "1 years old")
Eu gostaria de usar o grep apenas para o número numérico desse vetor. A saída esperada é um vetor:
c(20, 1)
Como faço para fazer isso?
Eu tenho uma string assim:
years<-c("20 years old", "1 years old")
Eu gostaria de usar o grep apenas para o número numérico desse vetor. A saída esperada é um vetor:
c(20, 1)
Como faço para fazer isso?
Respostas:
E se
# pattern is by finding a set of numbers in the start and capturing them
as.numeric(gsub("([0-9]+).*$", "\\1", years))
ou
# pattern is to just remove _years_old
as.numeric(gsub(" years old", "", years))
ou
# split by space, get the element in first index
as.numeric(sapply(strsplit(years, " "), "[[", 1))
.*
é necessário, pois você precisa corresponder a toda a string. Sem isso, nada é removido. Além disso, observe que sub
pode ser usado aqui em vez de gsub
.
gsub(".*?([0-9]+).*", "\\1", years)
gsub(".*?([0-9]+).*?", "\\1", "Jun. 27–30")
Resultado: [1] "2730" gsub(".*?([0-9]+)\\-.*?", "\\1", "Jun. 27–30")
Resultado: [1] "27 de junho –30 "
Acho que a substituição é uma forma indireta de se chegar à solução. Se você deseja recuperar todos os números, recomendo gregexpr
:
matches <- regmatches(years, gregexpr("[[:digit:]]+", years))
as.numeric(unlist(matches))
Se você tiver várias correspondências em uma string, todas elas serão obtidas. Se você estiver interessado apenas na primeira correspondência, use em regexpr
vez de gregexpr
e poderá pular o unlist
.
gregexpr
, regexpr
ou ambos?
gregexpr
. Eu não tinha tentado regexpr
até agora. Enorme diferença. Usar o regexpr
coloca entre as soluções de Andrew e Arun (o segundo mais rápido) em um conjunto 1e6. Talvez também seja interessante, usar sub
a solução de Andrew não melhora a velocidade.
Atualizar
Como extract_numeric
está obsoleto, podemos usar parse_number
do readr
pacote.
library(readr)
parse_number(years)
Aqui está outra opção com extract_numeric
library(tidyr)
extract_numeric(years)
#[1] 20 1
parse_number
que não brinca com números negativos. Teste parse_number("–27,633")
readr::parse_number("-12,345") # [1] -12345
Você também pode se livrar de todas as letras:
as.numeric(gsub("[[:alpha:]]", "", years))
Provavelmente, isso é menos generalizável.
Extraia números de qualquer string na posição inicial.
x <- gregexpr("^[0-9]+", years) # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))
Extraia números de qualquer string INDEPENDENTE de posição.
x <- gregexpr("[0-9]+", years) # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))
Também podemos usar str_extract
destringr
years<-c("20 years old", "1 years old")
as.integer(stringr::str_extract(years, "\\d+"))
#[1] 20 1
Se houver vários números na string e quisermos extrair todos eles, podemos usar o str_extract_all
qual, ao contrário, str_extract
retorna todos os 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"
Após a postagem de Gabor Grothendieck, poste na lista de discussão 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 o pacote unglue podemos fazer:
# install.packages("unglue")
library(unglue)
years<-c("20 years old", "1 years old")
unglue_vec(years, "{x} years old", convert = TRUE)
#> [1] 20 1
Criado em 06/11/2019 pelo pacote reprex (v0.3.0)
Mais informações: https://github.com/moodymudskipper/unglue/blob/master/README.md
.*
necessário? Se você quer no início, por que não usar^[[:digit:]]+
?