R言語:関数から複数の値(メインの値+オプショナルな値)を返したい場合

1 min read読了の目安(約1400字

R言語についてです。R言語で関数から複数の値を返したい場合、どうするのがよいか、盲点になるような方法に気づいたので、記事にしました。

listを使うのが常套手段

Rで複数の値を返したい場合の常套手段としては、listに値を入れて返すのが普通です。(Rのlistは動的言語の連想配列のようなものです。)

vectorを使う

vectorに入れてもよいのですが、vectorだと、integer、real(浮動小数点)、characterや logicalなどに限られて、さらに同じ型の要素しか入れられません。もちろん、そういう場合は、vectorでよいと思いますが、それでも、それぞれの意味が異なるものを返す場合はlistの方が親切だと思います。

他に方法は?

ここからは個人的な経験、感想になります。 普通にRだけでプログラムを書いているときは、思わなかったのですが、ある時、RCpp(Rの拡張をC++で書くためのフレームワーク)を使って、C/C++から結果を返すようなときに、list以外でなんとかできないかなと思うことがありました。そのRcppの関数は、もともとDataFrameを返していたのだけど、ある時、オプショナルな情報を返したいなと思いました。当然、listに入れればよいのですが、オプショナルな値がない場合でも、listに入ってしますので、その関数を使うときに、取り出すのも手間かなと思いました。Rの関数だと、返り値が、listやdata.frameかは、動的言語なので、どちらでもよいのですが、Rcppの関数から返す場合は、DataFrameかListかなど固定します(この点は回避方法あるかもしれませんが、静的言語のコンパイル時のチェックなども考えると、固定しておいた方が安全だと思います、という意味)。

Attributesがあった

結果、いろいろ考えて、そういえばRには、attributesがあったなと思いだし、使えるなと思いました。Rは、どのオブジェクトにも、attributesという付加的な情報を渡すことができます。身近な例では、vectorの要素に名前(タグ)をつけたり、Dimensionを設定したり、また、S3などといった、オブジェクトによって関数の挙動を変える仕組み(S3というオブジェクト指向)にも使われています。

R言語でのattr()のドキュメント

https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/attr
Rcppではこちらになります。
https://teuder.github.io/rcpp4everyone_en/202_attributes.html

常套手段ではないですが、attributesは絶対に変更になる機能ではないので、安心して使えると思います。オプショナルな情報を付加するという点で、正しい使い方だと思いますし。

なお、attributeの名前として、classは絶対避けないといけないですし、names, colnames, rownames, dimなど、他とかぶりそうなものは避けておく必要があります。自分は方針として、接頭辞をつけたり、内部的に使うだけで外にだすオブジェクトからは削除するようにしています(削除する場合は、NULLを割り当てます)。