У мене такий рядок:
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:]]+?