从字符串向量中提取数字


101

我有这样的字符串:

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

我只想从这个向量grep数字。预期输出是向量:

c(20, 1)

我该怎么做呢?

Answers:


83

怎么样

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

1
为什么有.*必要?如果您想一开始就使用它们,为什么不使用^[[:digit:]]+
sebastian-c

2
.*是必需的,因为您需要匹配整个字符串。没有那个,什么也不会清除。另外,请注意,sub此处可以使用代替gsub
马修·伦德伯格

12
如果数字不必在字符串的开头,请使用以下命令:gsub(".*?([0-9]+).*", "\\1", years)
TMS

我想得到27。我不明白为什么,通过添加条件(例如添加转义的“-”,结果会更长... gsub(".*?([0-9]+).*?", "\\1", "Jun. 27–30")结果:[1]“ 2730” gsub(".*?([0-9]+)\\-.*?", "\\1", "Jun. 27–30")结果:[1]“ 6月27日–30“
Lionel Trebuchon

65

我认为替代是解决方案的间接方式。如果要检索所有数字,我建议gregexpr

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

如果字符串中有多个匹配项,则将所有这些匹配项。如果您只对第一个比赛感兴趣,请使用regexpr代替,gregexpr然后跳过unlist


1
我没想到,但是这个解决方案比其他解决方案要慢一个数量级。
马修·伦德伯格

@MatthewLundberg的gregexprregexpr或两者兼而有之?
sebastian-c

1
gregexprregexpr直到现在我还没有尝试过。巨大的差异。regexpr在1e6集上,使用将其置于Andrew和Arun的解决方案之间(第二快)。也许也很有趣,sub在Andrew的解决方案中使用并不能提高速度。
Matthew Lundberg 2013年

这将根据小数点进行分割。例如2.5变成c('2','5')
MBorg

65

更新 由于extract_numeric不建议使用,我们可以使用parse_numberfrom readr包。

library(readr)
parse_number(years)

这是另一种选择 extract_numeric

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

2
对此应用程序很好,但请注意parse_number不要使用负数。试试 parse_number("–27,633")
荨麻

@Nettle是的,这是正确的,如果同时存在多个实例,也将不起作用
akrun

3
负数解析错误已修复:github.com/tidyverse/readr/issues/308 readr::parse_number("-12,345") # [1] -12345
Russ Hyde

35

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

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

as.numeric(sub("\\D+","",years))。如果前后有字母,那么gsub
Onyambu

21

或者简单地:

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

19

一个stringr流水线式的解决方案:

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

感谢Joe,但是此答案不会在字符串中的数字之前提取负号。
苗彩

16

您也可以删除所有字母:

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

虽然这可能不太普遍。


3
奇怪的是,在我的机器上,安德鲁的解决方案将其击败了5倍。
马修·伦德伯格

5

从任何字符串的起始位置提取数字。

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

4

我们也可以使用str_extractstringr

years<-c("20 years old", "1 years old")
as.integer(stringr::str_extract(years, "\\d+"))
#[1] 20  1

如果字符串中有多个数字,并且我们想提取所有数字,则可以使用str_extract_allstr_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"


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.