У мене такий рядок:
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
з readr
пакета.
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
Ви також можете позбутися всіх літер:
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
що на відміну від str_extract
повертає всі макти.
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]])
Використовуючи пакувальний неклей, ми можемо зробити:
# install.packages("unglue")
library(unglue)
years<-c("20 years old", "1 years old")
unglue_vec(years, "{x} years old", convert = TRUE)
#> [1] 20 1
Створено 06.11.2019 пакетом reprex (v0.3.0)
Більше інформації: https://github.com/moodymudskipper/unglue/blob/master/README.md
.*
потрібне? Якщо ви хочете їх на початку, чому б не використовувати^[[:digit:]]+
?