次のようなデータがあるとする。
N <- 100 x <- c("Apple", "Banana", "Candy") x <- rep(x, N) head(x)
[1] "Apple" "Banana" "Candy" "Apple" "Banana" "Candy"
このデータの中の全角文字を半角にしたい。
1. gsub を使う
base 関数にある gsub()
を使うと次のように書ける。
zenkaku <- c("A", "B", "C") hankaku <- c("A", "B", "C") use_gsub <- function(string, pattern, replacement) { for (i in seq_along(pattern)) { string <- gsub(pattern[i], replacement[i], string) } string } result <- use_gsub(x, zenkaku, hankaku) head(result)
[1] "Apple" "Banana" "Candy" "Apple" "Banana" "Candy"
2. str_replace を使う
stringr パッケージの str_replace_all()
を使っても同様に書ける。
library(stringr) use_str_replace <- function(string, pattern, replacement) { for (i in seq_along(pattern)) { string <- str_replace_all(string, pattern[i], replacement[i]) } string } result <- use_str_replace(x, zenkaku, hankaku) head(result)
[1] "Apple" "Banana" "Candy" "Apple" "Banana" "Candy"
速度を比較してみよう。
library(microbenchmark) microbenchmark( use_gsub = use_gsub(x, zenkaku, hankaku), use_str_replace = use_str_replace(x, zenkaku, hankaku) )
Unit: microseconds expr min lq mean median uq max neval use_gsub 2723.201 2977.7515 3116.3581 3172.952 3229.102 3511.901 100 use_str_replace 833.201 881.5005 938.3599 913.200 954.601 1331.201 100
str_replace
の方が 3倍ほど速いようである。
3. chartr を使う
base 関数には1文字置換を行う関数として chartr()
がある。
例えば次のように使う。
chartr(c("Apple", "Banana", "Candy"), old = "ABC", new = "ABC")
[1] "Apple" "Banana" "Candy"
old
と new
に同じ長さの文字列を渡すことで、同じ場所にある文字が置換される。
上の例で言えば、old
の1番目の文字 A
は new
の1番目の文字 A
に置換される。
2番目3番目も同様である。
これを使うと次のように書ける。
zenkaku_string <- paste(zenkaku, collapse = "") hankaku_string <- paste(hankaku, collapse = "") use_chartr <- function(string, old, new) { chartr(string, old = old, new = new) } result <- use_chartr(x, zenkaku_string, hankaku_string) head(result)
[1] "Apple" "Banana" "Candy" "Apple" "Banana" "Candy"
速度を比較してみる。
microbenchmark( use_gsub = use_gsub(x, zenkaku, hankaku), use_str_replace = use_str_replace(x, zenkaku, hankaku), use_chartr = use_chartr(x, zenkaku_string, hankaku_string) )
Unit: microseconds expr min lq mean median uq max neval use_gsub 2637.301 2664.200 2724.2630 2703.4010 2741.4510 3214.301 100 use_str_replace 816.502 834.501 866.4410 852.5505 881.7510 1176.602 100 use_chartr 100.801 103.251 106.9551 106.7010 108.4505 148.902 100
str_replace
の 10倍、gsub
の 30倍くらい速い。
4. str_replace の別解
str_replace
ではこんなことができるそうだ。
str_replace_allもいいですぞ!
— atusy (@Atsushi776) 2020年3月21日
> 'ももくり3年' %>% str_replace_all(c('もも' = '桃', 'くり' = '栗'))
[1] "桃栗3年"
これを使えば次のように書ける。
library(stringr) pattern <- hankaku names(pattern) <- zenkaku use_str_replace2 <- function(string, pattern) { str_replace_all(string, pattern) } result <- use_str_replace2(x, pattern) head(result)
[1] "Apple" "Banana" "Candy" "Apple" "Banana" "Candy"
速度を比較してみる。
microbenchmark( use_gsub = use_gsub(x, zenkaku, hankaku), use_str_replace = use_str_replace(x, zenkaku, hankaku), use_str_replace2 = use_str_replace2(x, pattern), use_chartr = use_chartr(x, zenkaku_string, hankaku_string) )
Unit: microseconds expr min lq mean median uq max neval use_gsub 2746.401 2794.5510 3060.284 2912.0010 3235.4015 5110.902 100 use_str_replace 830.901 890.4515 944.777 914.8505 964.2015 1290.900 100 use_str_replace2 485.400 501.2510 557.874 525.4015 566.4010 2074.200 100 use_chartr 104.401 111.3510 120.510 115.2510 128.8010 228.401 100
通常の str_replace
の2倍くらい速くなったが、chartr
には敵わなかった。
5. まとめ
1文字置換を行うときは chartr
を使うと良い。
Enjoy!