2016-07-27 3 views
0

私は株式ティッカーの文字ベクトルを持っています。ここでティッカー名は、ティッカーがcountry_name/ticker_nameの形式に基づいている国に連結されています。私は各文字列を分割し、 '/'バックからすべてを削除しようとしていて、テロップ名だけの文字ベクトルを返しています。ここにベクトル例があります:正規表現(R)の前に文字を削除する

sample_string <- c('US/SPY', 'US/AOL', 'US/MTC', 'US/PHA', 'US/PZI', 
        'US/AOL', 'US/BRCM') 

私の最初の考えは、stringrライブラリを使用することです。私は実際にそのパッケージでの経験を持っているが、ここで私がしようとしていたものですありません。

library(stringr) 
split_string <- str_split(sample_string, '/') 

をしかし、私は、単一のベクトルとして、各リストの唯一の第二の要素を返す方法が不明でした。

私はこれを大規模な文字ベクトル(1億500万エントリ)でどうやって行うのですか?

+2

これを達成する方法はたくさんあります。例えば ​​'sub("。* /(。*) "、" \\ 1 "、sample_string)' OR 'sub("。*/"、" "、sample_string)'などです。正規表現を避けるdata.table :: tstrsplit(sample_string、 "/"、fixed = TRUE)[[2]] ' –

+0

'。* /(。*)'はここでポインタとして機能しますか? –

+0

"*バックスラッシュの前にすべてをマッチさせて(それを含む)すべてのものをキャプチャする"という意味です。 '\\ 1'は捕捉されたグループを返すように' sub'に指示します。このケースでは、それは過剰補完だと私は思うが。他の2つのオプションはおそらくより良い/よりシンプルです。いずれにしても、このタイプの質問は何度も尋ねられましたので、Rでより多くの正規表現の例を見たい場合は、実際にGoogleを試してください。このサイトは、将来の正規表現のテストhttps://regex101.com/とチュートリアルのためのこの1つはhttp://www.regular-expressions.info/tutorial.html –

答えて

3

@David Arenburgで提案されているすべての方法や、stringrパッケージのstr_extractを使用した別のベンチマークがあります。

sample_string <- rep(sample_string, 1000000) 

library(data.table); library(stringr) 
s1 <- function() sub(".*/(.*)", "\\1", sample_string) 
s2 <- function() sub(".*/", "", sample_string) 
s3 <- function() str_extract(sample_string, "(?<=/)(.*)") 
s4 <- function() tstrsplit(sample_string, "/", fixed = TRUE)[[2]] 

length(sample_string) 
# [1] 7000000 

identical(s1(), s2()) 
# [1] TRUE 
identical(s1(), s3()) 
# [1] TRUE 
identical(s1(), s4()) 
# [1] TRUE 

microbenchmark::microbenchmark(s1(), s2(), s3(), s4(), times = 5) 
# Unit: seconds 
# expr  min  lq  mean median  uq  max neval 
# s1() 3.916555 3.917370 4.046708 3.923246 3.925184 4.551184  5 
# s2() 3.584694 3.593755 3.726922 3.610284 3.646449 4.199426  5 
# s3() 3.051398 3.062237 3.354410 3.138080 3.722347 3.797985  5 
# s4() 1.908283 1.964223 2.349522 2.117521 2.760612 2.996971  5 

tstrsplitの方法が最も高速です。

更新は:

@Frankから別のメソッドを追加し、この比較は、実際のデータに依存する厳密に正確ではありませんsample_stringが上記で製造されたように複製例がたくさんある場合、利点があります非常に明白:

s5 <- function() setDT(list(sample_string))[, v := tstrsplit(V1, "/", fixed = TRUE)[[2]], by=V1]$v 

identical(s1(), s5()) 
# [1] TRUE 

microbenchmark::microbenchmark(s1(), s2(), s3(), s4(), s5(), times = 5) 
# Unit: milliseconds 
# expr  min  lq  mean median  uq  max neval 
# s1() 3905.97703 3913.264 3922.8540 3913.4035 3932.2680 3949.3575  5 
# s2() 3568.63504 3576.755 3713.7230 3660.5570 3740.8252 4021.8426  5 
# s3() 3029.66877 3032.898 3061.0584 3052.6937 3086.9714 3103.0604  5 
# s4() 1322.42430 1679.475 1985.5440 1801.9054 1857.8056 3266.1101  5 
# s5() 82.71379 101.899 177.8306 121.6682 209.0579 373.8141  5 
+1

サンプルの長さはいいですが、それを作るコードを表示してみませんか? – Frank

+1

@Frank OPのsample_stringを100万回繰り返しました。答えに追加されました。 – Psidom

+1

繰り返される多数の値の乱用... s5 < - function()setDT(list(sample_string))[、v:= tstrsplit(V1、 "/"、fixed = TRUE)[[2]]、by = V1 ] $ v'彼らはAOLを2回持っているので、OPと同様に関連性があるかもしれない。これは、s4と10x-ishと同じものとしてテストします。 – Frank

2

あなたの質問についていくつかの有用な注意事項:まず、あなたはそれがlapply呼び出すことによって、何をしたいかないstringrパッケージでstr_split_fixed機能があります。それは第二に、別の方法は、リストの各第二の要素を抽出することを考えるようにstringi::stri_split_fixedを呼び出すことによって動作し、

do.call("c", lapply(str_split(sample_string, '/'),"[[",2)) 

に異ならないです

library(data.table); library(stringr) 
sample_string <- c('US/SPY', 'US/AOL', 'US/MTC', 'US/PHA', 'US/PZI', 
        'US/AOL', 'US/BRCM') 
sample_string <- rep(sample_string, 1e5) 
split_string <- str_split_fixed(sample_string, '/', 2)[,2] 

tstrsplitが内部的に行っていることを正確に何をすることです。総サイドノートで

transpose(strsplit(sample_string, "/", fixed = T))[[2]] 

、上記tstrsplitを呼び出すよりもわずかに速くする必要があります。これはもちろん、おそらく長さを入力する価値はありませんが、関数が何をしているかを知るのに役立ちます。

library(data.table); library(stringr) 
s4 <- function() tstrsplit(sample_string, "/", fixed = TRUE)[[2]] 
s5 <- function() transpose(strsplit(sample_string, "/", fixed = T))[[2]] 

identical(s4(), s5()) 
microbenchmark::microbenchmark(s4(), s5(), times = 20) 

microbenchmark::microbenchmark(s4(), s5(), times = 20) 
Unit: milliseconds 
expr  min  lq  mean median  uq  max neval 
s4() 161.0744 193.3611 255.8136 234.9945 271.6811 434.7992 20 
s5() 140.8569 176.5600 233.3570 194.1676 251.7921 420.3431 20 

2つの要素とのそれぞれは、長さ2のリストに700万要素と各あなたの結果を変換する、長さ700万このリストを転置要するに、この第二の方法、に関する。このリストの2番目の要素を抽出します。

+0

注: 'transpose'はdata.tableパッケージ内の関数でもあります。ちょうどtstrsplitでも可能でしょうか?また、移調自体はCで書かれているようです。 – Frank

+0

@Frank、そうです。それを反映するために私の答えを編集しました。その違いは何ですか?関数のオーバーヘッド?または、RのC関数がdata.tableのC関数よりも転置で高速である可能性があります。私は後でいくつか調べる必要があるだろうと思う。 – shayaa

+0

Hm、差は小さい。私はそれについて心配しません。あなたが推測したように、おそらくオーバーヘッド。私はちょうどいくつかのミリ秒のためにその内部に掘り下げるのではなく、ラッパー(tstrsplit)を使っています。同様に、ベースから '.subset2'や' .Internal(mean(x)) 'を使っていません。それらははるかに大きなパフォーマンスの向上を提供します。http://stackoverflow.com/a/17010701/およびhttp://stackoverflow.com/questions/14209427/improve-performance-function#comment19719256_14213913 – Frank

関連する問題