ほくそ笑む

R言語と統計解析について

R で 1文字置換を行うときは chartr を使う

次のようなデータがあるとする。

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" 

oldnew に同じ長さの文字列を渡すことで、同じ場所にある文字が置換される。 上の例で言えば、old の1番目の文字 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 ではこんなことができるそうだ。

これを使えば次のように書ける。

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!