niszetの日記

細かい情報を載せていくブログ

(R)アルファベットが連続したベクトルが欲しい(小ネタ)

最初躓きますよね?

Rの最初の最初、ベクトルとはどんなものかみたいな話からはじまって、

seq(1,5)
# [1] 1 2 3 4 5

とか、

rep(1,5)
# [1] 1 1 1 1 1

とかで、わーい!ってやっていた時期があると思います。で、seq(1,5)の代わりに1:5でもいけるよ!すげーじゃん!!

で、じゃあアルファベットも・・・って試して、

"a":"z"
#  "a":"z" でエラー:  引数が NA/NaN です 
#  追加情報:  警告メッセージ: 
# 1:  強制変換により NA が生成されました  
# 2:  強制変換により NA が生成されました  

あると思います。

lettersを使う

baseパッケージに、lettersというデータがあるので、これを使います。これが正解。あと、大文字でLETTERSもある。

letters
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"

全てのアルファベットについてチェックしようとかいう場合は、c(letters,LETTERS)でつなげればよろしい。

あと余談ですが、:も関数なので、:(1,5) で 1:5 と同じ結果になりますし、ベクトルなので、要素をインデックスで指定して

letters[c(1,26,26,1)]
# [1] "a" "z" "z" "a"

みたいになりますね。

なんか思いついた場合

C言語とかで文字を扱う場合、文字コードがaからzまで連番だから・・・という考え方で、上記のような連番生成できるんじゃないの?みたいな考えになりますよね。

じゃあそれでやってみるか。とはいえ、文字から数字への変換はNAになってしまうし...というところでハマりがちですが、Rにはraw型があります。ただ、文字からrawへの変換はcharToRawなので注意が必要ですね。

charToRaw("a")
# [1] 61
as.integer(charToRaw("a"))
# [1] 97

raw型は出力が16進数であらわされているのに注意です。10進数にするにはas.integerです。:はraw型を受け付けてくれないので、このように一旦integerにして、それを使い、raw型に戻し、rawからcharへの変換をかけます。

つまり、以下のようになります。

rawToChar(as.raw(`:`(as.integer(charToRaw("a")),as.integer(charToRaw("z")))), multiple = T)
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"

ここで、rawToCharに引数multiple = Tを与えないと、文字がすべて結合されてしまうため注意。

一応、一致を確認してみると、

identical(letters, rawToChar(as.raw(`:`(as.integer(charToRaw("a")),as.integer(charToRaw("z")))), T))
# [1] TRUE

となり、ちゃんと生成できましたね。

めでたしめでたし。