R: 多次元配列の要素をベクトルで指定する

投稿者: | 2017年9月27日

概要

  • R で多次元配列(行列)の要素にアクセスする時、インデックスをベクトルで指定したい
  • 普通のベクトルで指定しても期待した挙動をしてくれない
  • 多次元インデックスを指定するときは行ベクトルを使う

多次元配列

R では、array によって多次元配列を表現します。
例えば、次のような三次元配列を作ることができます。

要素へのアクセス

多次元配列の要素へのアクセスは、
それぞれの次元におけるインデックスを
x[i,j,k] のように指定します。

例えば、(2,1,2) の要素にアクセスしたい場合は

とすれば、配列に格納された値 8 が返されます。

変数でインデックスを指定したい

上記の要素アクセスがもっとも一般的な方法ですが、
これだと不便に感じることがあります。

不便さの原因は、要素を取り出すためのキーが、
2,1,2 と、特に決まったデータ型を持っていないためです。
そのため、インデックスを変数 key に代入して、
x[key] でアクセスできません。

この絶妙な使いづらさのために、
自分は array の代わりに list を使うことがよくありました。
つまり、2,1,2 を文字列として、
key = “2,1,2” で要素にアクセスするという方法です。

それはそれで気持ち悪いな、
もっといい方法はないかなと思いながら、何年も使ってきました。
そして、ようやく、納得できそうな方法を見つけたので、
ここにメモとして残しておきます。

ベクトルでインデックスを指定する

何も知らない人が、
配列のインデックス (2,1,2) を指定する時、
普通は、ベクトル c(2,1,2) で要素を指定するのではないかと思います。

ところが、R では、ベクトルをインデックスとした要素アクセスは、
期待した挙動してくれません。

実際、そのような要素アクセスをすると、

一つの要素にアクセスしようとしたのに、
複数の要素が返ってきてしまいました。

これは、多次元配列を一次元配列に並べ直した

のインデックス 2,1,2 を指定してアクセスしたことになっています。

この挙動をみて、ベクトルでのインデックス指定を諦めた人もいるのではないでしょうか。
私もその一人です。

答えは行ベクトル

実は上のベクトルでの指定は惜しい線までいっていたのです。
array はインデックスをベクトルで指定できますが、
その時のベクトルは、行ベクトルである必要があります。

R では、通常、ベクトルは列ベクトルとして扱われるので、
かなり引っかかりやすい罠だと思います。

実際に、インデックス (2,1,2) を行ベクトル t(c(2,1,2)) で指定して、
要素にアクセスしてみると、

この通り、(2,1,2) に格納された 8 を返してくれました。

複数の要素にもアクセスできる

行ベクトルでアクセスできると分かってしまえば、
行ベクトルを並べた行列でインデックスを指定すれば、
複数の要素アクセスもできるのではないかと期待されます。

実際、その通りで、 インデックス (2,1,2) と (2,2,1) を rbind で行に並べてみると

(2,1,2) と (2,2,1) に格納された 8 と 5 に同時にアクセスできていることが分かります。

まとめ

長年 R を使ってきて、
「なんでベクトルでインデックスを指定できるようにしてないんだろう」
と疑問でしたが、実はできたのですね。

行ベクトルで指定すればいいと分かってしまえば簡単な話ですが、
通常は列ベクトルとして扱われるという R のルールも相まって、
かなり気づきにくいのではないでしょうか。

きっと、悩んでいたのは自分だけではない(はず)と思います。


 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です