文字列のベクトルから数値を抽出する


101

私はこのような文字列を持っています:

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

このベクトルの数値のみをgrepしたいと思います。期待される出力はベクトルです:

c(20, 1)

これを行うにはどうすればよいですか?

回答:


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 2013

2
.*文字列全体と一致させる必要があるため、それがなければ、何も削除されません。また、のsub代わりにここで使用できることに注意してくださいgsub
Matthew Lundberg、2013年

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 "
ライオネルトレブション

65

置換は、解決策を得る間接的な方法だと思います。すべての数値を取得したい場合は、次のことをお勧めしgregexprます。

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

文字列に複数の一致がある場合、これはそれらすべてを取得します。最初の一致のみに関心がある場合は、regexpr代わりにgregexprを使用して、をスキップできますunlist


1
予想はしていませんでしたが、このソリューションは他のソリューションよりも桁違いに遅いです。
Matthew Lundberg 2013年

@MatthewLundberg the gregexprregexprまたは両方?
sebastian-c 2013

1
gregexprregexpr今まで試していませんでした。大きな違い。を使用regexprすると、1e6セットでAndrewとArunのソリューション(2番目に速い)の間に配置されます。おそらく興味深いかもしれsubませんが、Andrewのソリューションで使用しても速度は向上しません。
Matthew Lundberg、2013年

これは小数点に基づいて分割されます。たとえば、2.5はc( '2'、 '5')になります
MBorg

65

更新extract_numericは非推奨な のでparse_numberreadrパッケージから使用できます。

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

これは、より単純なPerlのような正規表現を使用した、Arunの最初のソリューションの代替案です。

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
奇妙なことに、Andrewのソリューションは、私のマシンではこれを5倍上回っています。
Matthew Lundberg、2013年

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_extractからも使用できますstringr

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

文字列に複数の数値があり、それらすべてを抽出したい場合は、thisを使用するstr_extract_allと、 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"


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.