从字符串向量中提取数字

我有这样的线:

years<-c("20 years old", "1 years old")

我希望只抓取这个向量中的数字。预期输出是一个向量:

c(20, 1)

我该怎么做呢?

244619 次浏览

怎么样

# 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))

下面是 Arun 的第一个解决方案的一个替代方案,它有一个更简单的类似 Perl 的正则表达式:

as.numeric(gsub("[^\\d]+", "", years, perl=TRUE))

你也可以把所有的字母都处理掉:

as.numeric(gsub("[[:alpha:]]", "", years))

不过,这可能不太具有普遍性。

我认为替代是获得解决方案的间接途径。如果你想检索所有的数字,我建议 gregexpr:

matches <- regmatches(years, gregexpr("[[:digit:]]+", years))
as.numeric(unlist(matches))

如果在一个字符串中有多个匹配项,这将获取所有匹配项。如果您只对第一个匹配感兴趣,使用 regexpr而不是 gregexpr,您可以跳过 unlist

后从 Gabor Grothendieck 发布在 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]])

或者简单地说:

as.numeric(gsub("\\D", "", years))
# [1] 20  1

更新 由于不推荐使用 extract_numeric,我们可以使用 readr包中的 parse_number

library(readr)
parse_number(years)

这是 extract_numeric的另一个选项

library(tidyr)
extract_numeric(years)
#[1] 20  1

stringr流水线解决方案:

library(stringr)
years %>% str_match_all("[0-9]+") %>% unlist %>% as.numeric

从任意字符串的开始位置提取数字。

x <- gregexpr("^[0-9]+", years)  # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))

从任何位置的字符串 INDEPENDENT 中提取数字。

x <- gregexpr("[0-9]+", years)  # Numbers with any number of digits
x2 <- as.numeric(unlist(regmatches(years, x)))

我们也可以使用 stringr中的 str_extract

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"

我们可以使用 解开胶水软件包:

# install.packages("unglue")
library(unglue)


years<-c("20 years old", "1 years old")
unglue_vec(years, "{x} years old", convert = TRUE)
#> [1] 20  1

Reprex 软件包于2019-11-06年度创作(0.3.0版)

更多信息: https://github.com/moodymudskipper/unglue/blob/master/README.md

我对这个问题很感兴趣,因为它适用于从 base::summary()函数中提取值。要从表中提取值,您可能需要考虑的另一个选项是构建一个函数,该函数接受 summary()表中的任何条目并将其转换为有用的数字。例如,如果你得到:

(s <- summary(dataset))


sv_final_num_beneficiarios  sv_pfam_rec        sv_area_transf
Min.   :    1.0            Min.   :0.0000036   Min.   :0.000004
1st Qu.:   67.5            1st Qu.:0.0286363   1st Qu.:0.010107
Median :  200.0            Median :0.0710803   Median :0.021865
Mean   :  454.6            Mean   :0.1140274   Mean   :0.034802
3rd Qu.:  515.8            3rd Qu.:0.1527177   3rd Qu.:0.044234
Max.   :17516.0            Max.   :0.8217923   Max.   :0.360924

你可能需要提取 sv_pfam_rec1st Qu并读取第二行的第二个 col. 为了得到格式化的单个值,我做了一个函数

s_extract <- function(summary_entry){
separate(as_tibble(summary_entry),
sep = ":",
col = value,
remove = FALSE,
into = c("bad", "good"))[[3]] %>%
as.numeric()
}

您只需要提供一个摘要条目,例如 summary_entry = s[3,3],就可以获得 sv_area_transfMedian

如果这个函数是基于 separate()的,那么在某些变量名也包含数字的情况下,导航起来就更容易了