У меня есть такая строка:
years<-c("20 years old", "1 years old")
Я хотел бы получить только числовое число из этого вектора. Ожидаемый результат - вектор:
c(20, 1)
Как мне это сделать?
У меня есть такая строка:
years<-c("20 years old", "1 years old")
Я хотел бы получить только числовое число из этого вектора. Ожидаемый результат - вектор:
c(20, 1)
Как мне это сделать?
Ответы:
Как насчет
# pattern is by finding a set of numbers in the start and capturing them
as.numeric(gsub("([0-9]+).*$", "\\1", years))
или
# pattern is to just remove _years_old
as.numeric(gsub(" years old", "", years))
или
# split by space, get the element in first index
as.numeric(sapply(strsplit(years, " "), "[[", 1))
.*
необходимо, так как вам нужно сопоставить всю строку. Без этого ничего не удаляется. Также обратите внимание, что здесь sub
можно использовать вместо gsub
.
gsub(".*?([0-9]+).*", "\\1", years)
gsub(".*?([0-9]+).*?", "\\1", "Jun. 27–30")
Результат: [1] «2730» gsub(".*?([0-9]+)\\-.*?", "\\1", "Jun. 27–30")
Результат: [1] «27 июня –30 »
Я думаю, что подмена - это косвенный путь к решению. Если вы хотите получить все числа, я рекомендую gregexpr
:
matches <- regmatches(years, gregexpr("[[:digit:]]+", years))
as.numeric(unlist(matches))
Если у вас есть несколько совпадений в строке, он получит их все. Если вас интересует только первое совпадение, используйте regexpr
вместо, gregexpr
и вы можете пропустить unlist
.
gregexpr
, regexpr
или оба?
gregexpr
. Я не пробовал regexpr
до сих пор. Огромная разница. Использование regexpr
ставит его между решениями Эндрю и Аруна (второе место по скорости) в сете 1e6. Возможно, также интересно, что использование sub
в решении Эндрю скорости не улучшает.
Обновление,
поскольку extract_numeric
устарело, мы можем использовать parse_number
from readr
package.
library(readr)
parse_number(years)
Вот еще вариант с extract_numeric
library(tidyr)
extract_numeric(years)
#[1] 20 1
parse_number
оно не играет с отрицательными числами. Попробуй parse_number("–27,633")
readr::parse_number("-12,345") # [1] -12345
Вот альтернатива первому решению Аруна с более простым регулярным выражением, похожим на Perl:
as.numeric(gsub("[^\\d]+", "", years, perl=TRUE))
as.numeric(sub("\\D+","",years))
. Если были буквы до и или после, тоgsub
Вы также можете избавиться от всех букв:
as.numeric(gsub("[[:alpha:]]", "", years))
Скорее всего, это менее универсально.
Извлеките числа из любой строки в начальной позиции.
x <- gregexpr("^[0-9]+", years) # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))
Извлекайте числа из любой строки НЕЗАВИСИМО от позиции.
x <- gregexpr("[0-9]+", years) # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))
Мы также можем использовать str_extract
отstringr
years<-c("20 years old", "1 years old")
as.integer(stringr::str_extract(years, "\\d+"))
#[1] 20 1
Если в строке есть несколько чисел, и мы хотим извлечь их все, мы можем использовать str_extract_all
which, в отличие от str_extract
возвращающих все 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"
После сообщения Габора Гротендика в списке рассылки 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]])
Используя пакет unglue, мы можем:
# install.packages("unglue")
library(unglue)
years<-c("20 years old", "1 years old")
unglue_vec(years, "{x} years old", convert = TRUE)
#> [1] 20 1
Создано 2019-11-06 пакетом REPEX (v0.3.0)
Подробнее: https://github.com/moodymudskipper/unglue/blob/master/README.md
.*
нужно? Если вы хотите их с самого начала, почему бы не использовать^[[:digit:]]+
?