クボセンセーとのやりとりで出てきたstringiパッケージのサワリです。
stringiとはバックエンドにICUを採用してゴニョゴニョできるようになりつつ、 処理本体をCでゴニョゴニョすることで高速な文字列処理を可能とする ハドレー教の一宗派である。
だそうです。 ハドレー教だけあって、APIはstringrのそれを採用してます。 str_hoge_hogeをstri_hoge_hogeにすればだいたいのことはできます。
ちなみにここで挙げてる以外にも高速便利関数がたくさんあります。 あ、%>%をオーバーロードしてるので、dplyrと一緒に使っちゃダメです。 この問題、いい加減なんとかした方がいいと思うんだけど・・・。
sessionInfo()
## R version 3.1.1 (2014-07-10)
## Platform: x86_64-apple-darwin13.1.0 (64-bit)
##
## locale:
## [1] ja_JP.UTF-8/ja_JP.UTF-8/ja_JP.UTF-8/C/ja_JP.UTF-8/ja_JP.UTF-8
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## loaded via a namespace (and not attached):
## [1] digest_0.6.4 evaluate_0.5.5 formatR_1.0 htmltools_0.2.6
## [5] knitr_1.6.22 rmarkdown_0.3.8 stringr_0.6.2 tools_3.1.1
## [9] yaml_2.1.13
ベンチマークについては一部、公式 http://www.rexamine.com/2014/05/stringi-0-2-3-released/ あたりから借りてますぅ
set.seed(42)
library(knitr)
opts_chunk$set(cache=TRUE, cache.extra = 1)
options(width = 1000)
library(microbenchmark)
library(stringi)
library(stringr)
# 10文字のランダム文字列が1e+05個だよー
str = stri_rand_strings(1e+05, 10)
head(str)
## [1] "uwHpdWj8eh" "SivFSwy7TY" "u8zw5VOuRp" "joOg0p0Cub" "NR2yQxtdyc" "KLOm2kfAGV"
# 日本語もやってみるよー
strj = stri_rand_strings(1e+05, 10, pattern = "[あ-ん]")
head(strj)
## [1] "でっよくぬっねってけ" "はへぼのくゅえぎあぜ" "ささゐがすぽまきをご" "まふあねさのりそふに" "へべおゑふぱつへうけ" "うのめづづらうゐすね"
stringi速い。stringrが微妙に遅いわー
microbenchmark(stri_detect_fixed(str, "abba"),
str_detect(str, fixed("abba")),
grepl("abba", str, fixed=TRUE))
## Unit: milliseconds
## expr min lq mean median uq max neval
## stri_detect_fixed(str, "abba") 4.035864 4.185468 5.601303 4.327253 4.939369 62.68688 100
## str_detect(str, fixed("abba")) 7.661898 7.884671 11.043578 8.209151 14.902786 69.43982 100
## grepl("abba", str, fixed = TRUE) 5.516206 5.639213 7.124968 5.743263 6.063265 23.74515 100
microbenchmark(stri_detect_regex(str, "a..a"),
str_detect(str, "a..a"),
grepl("a..a", str))
## Unit: milliseconds
## expr min lq mean median uq max neval
## stri_detect_regex(str, "a..a") 15.75550 16.14140 17.93948 16.64575 18.22624 35.71516 100
## str_detect(str, "a..a") 36.25395 36.89241 40.41848 37.57298 44.42513 90.86483 100
## grepl("a..a", str) 33.86655 34.54136 36.49452 35.01991 37.74537 48.05728 100
圧倒的だな
microbenchmark(stri_detect_fixed(strj, "なめこ"),
str_detect(strj, fixed("なめこ")),
grepl("なめこ", strj, fixed=TRUE),
times = 10)
## Unit: milliseconds
## expr min lq mean median uq max neval
## stri_detect_fixed(strj, "なめこ") 16.10392 16.47598 16.88976 16.52027 16.89350 19.67792 10
## str_detect(strj, fixed("なめこ")) 33.16463 33.70853 37.24028 34.96871 41.07442 44.50666 10
## grepl("なめこ", strj, fixed = TRUE) 31.39783 31.59830 32.57676 32.27361 33.56419 34.31391 10
microbenchmark(stri_detect_regex(strj, "な.こ"),
str_detect(strj, "な.こ"),
grepl("な.こ", strj),
times = 10)
## Unit: milliseconds
## expr min lq mean median uq max neval
## stri_detect_regex(strj, "な.こ") 28.38939 28.97387 37.43506 30.35704 42.53637 61.67056 10
## str_detect(strj, "な.こ") 76.02259 76.24321 89.42131 83.96264 93.42407 127.20450 10
## grepl("な.こ", strj) 66.49910 73.82659 78.99823 79.45426 82.14890 88.46347 10
ところで「なめこ」ってあるんですかね。
(n <- sum(stri_detect_fixed(strj, "なめこ")))
## [1] 3
おー、3個ありました。
そこそこ速い。
microbenchmark(stri_replace_all_regex(strj, "な.こ", "なめこ"),
str_replace_all(strj, "な.こ", "なめこ"),
gsub("な.こ", "なめこ", strj),
times = 10)
## Unit: milliseconds
## expr min lq mean median uq max neval
## stri_replace_all_regex(strj, "な.こ", "なめこ") 84.46038 85.6175 87.76002 87.3060 88.68601 93.48167 10
## str_replace_all(strj, "な.こ", "なめこ") 106.60033 109.4666 115.89717 115.8674 121.70633 123.02140 10
## gsub("な.こ", "なめこ", strj) 100.89139 110.6775 112.63626 112.8713 117.52663 120.71247 10
なめこ何個になりましたかね。
(n <- sum(stri_detect_fixed(stri_replace_all_regex(strj, "な.こ", "なめこ"), "なめこ")))
## [1] 138
138個 ^^/
han <- "ダイダ、オレ"
(ret <- stri_trans_nfkc(han))
## [1] "ダイダ、オレ"
ret == "ダイダ、オレ"
## [1] TRUE
ちなみにnfkdだとちょっと違います。
han <- "ダイダ、オレ"
(ret <- stri_trans_nfkd(han))
## [1] "ダイダ、オレ"
ret == "ダイダ、オレ"
## [1] FALSE
iconv(ret, "utf-8-mac", "utf-8", ret) == "ダイダ、オレ"
## [1] TRUE
マジデヤミ
「Rで前処理が、、、文字列処理ができない・・・何故だ?」
「坊やだからさ」
PythonにできてRにできないことはオフサイドルールによるブロック表現だけですからっ!
Enjoy!!