2  再現可能性

R言語を使ったデータ分析において、結果が再現しない原因は何でしょうか。 原因を知ることで対策を講じることができます。 ここでは、Rを扱ううえでの再現性を阻害する要因を紹介します。

2.1 再現性を阻害する要因

R言語はプログラミング言語の一種であるため、プログラムやデータによって結果が変わることがあります。 特に意識しておくべき要因として、以下のようなものがあります。

  • 環境、環境変数の違い
  • ランダム性

環境については前章で述べたとおり、 Rのバージョンやパッケージのバージョン、OSなどが該当します。

環境変数とは、名前の通り、環境に関する情報を保持する変数のことです。 R言語では、環境変数を設定することで、Rの挙動を変えることができます。

もう一つのランダム性は、乱数を利用する関数を使う場面で発生します。 乱数を使う関数は、実行のたびに異なる値を返すために再現性が損なわれる原因となります。

具体例を見てみましょう。 標準正規分布に従う乱数を、rnorm関数を使って生成してみます。 同じ関数・引数であっても実行のたびに異なる結果が得られます。

# 乱数生成アルゴリズムを利用する関数では、実行の度に出力が変化する。
rnorm(n = 1)
[1] -0.7136604
rnorm(n = 1)
[1] -0.1216059

乱数の利用は、シミュレーションやモンテカルロ法などの分野で重要ですが、 再現性を確保するためには、set.seed()関数を使って乱数生成アルゴリズムのシードを固定する必要があります。

set.seed(123)

rnorm(n = 1)
[1] -0.5604756

set.seed()関数は、乱数を利用する関数の実行前に呼び出します。 引数には単一の整数を指定します。 この値が乱数のシードとして使われ、同じシードを指定すると同じ乱数が生成されるようになり、結果が再現可能になります。

そのため、私は上記の結果がどのような値になるかを知っています。 私の予言が正しければ、 -0.5604756となるはずです。 乱数はRのさまざまな関数で利用されるため、再現性が求められる場面ではset.seed()関数を意識することが大事です。

.Rprofile

Rでは、.Rprofileに書かれた内容が起動時に実行されます。 このファイルは起動時に読み込まれるので、Rの起動中に適用するオプションや環境変数などが記述されます。 これにより、毎回オプションを設定する手間が省けます。 よく使うパッケージを読み込む、デフォルトのグラフィックデバイスを設定する、さまざまな指定が可能です。

2.1.1 reprexパッケージ

ソースコードが再現性をもつことや、第三者に状況を伝えるためには、再現可能な例を示す必要があります。 ここでの再現可能には、エラーの出力も含まれます。 reprexパッケージを使うと、Rのコードとその出力を含む再現可能な例(reproducible example)を作成できます。

使い方は、reprex()関数内に再現の対象とするコードを記述し、実行するだけです。

library(reprex)
reprex({
  set.seed(123)
  rnorm(n = 1)
})

コードを実行すると、実行中のRセッションとは別のRセッションが立ち上がり、再現可能な例が作成されます。 作成された例は、コンソールに表示されるだけでなく、クリップボードにコピーされるため、簡単に共有できます。 外部出力のために結果をテキストファイルに保存することもできます。

reprexパッケージの便利な点は、実行環境の情報も含めて再現可能な例を作成できることです。 reprex()関数の引数にsession_info = TRUEを指定すると、セッション情報も出力されるので、コードの外にある環境についても再現性を検証する題材として使えるようになります。

# session_info = TRUEを指定すると、セッション情報も出力される。
# wd引数で作業ディレクトリを指定する。ここでは現在の作業ディレクトリを指定し、実行コードと結果が外部ファイルに保存するようにした。
reprex({
  print("hello")
}, 
  session_info = TRUE, 
  wd = ".")

実際、Rコードの不具合を報告する際には、再現可能な例を示すことが求められることがあります。 GitHub issuesやStack Overflow、Slackなどで質問する際には、reprexパッケージを使って再現可能な例を作成すると、問題の解決がスムーズに進むことがあります。

2.2 rig

Rを使ったデータ分析を行う際、複数のRのバージョンを使い分ける必要が生じることがあります。 古いバージョンのRで書かれたソースコードを実行する場合、新しいバージョンとは結果が変わっている可能性があります。 これにはデフォルトの挙動の変化1や乱数生成のアルゴリズムの変更2などが影響します。

Rでは、4.14.0のようにマイナーバージョンごとに異なるバージョンを共存させることが可能ですが、実際にバージョンを切り替えるのは手間がかかります。 そこで、Rのバージョン管理ツールであるrigが役立ちます。 rigを使うことで、複数のRのバージョンを共存、切り替えが容易に行えるようになります。

リリースされている最新のRをインストールするには以下のコマンドを実行します。

rig add release

また、macOS限定になりますが、メニューバーからRStudioのプロジェクト機能(第3章参照)と連動し、最近起動したrprojファイルを任意のバージョンで起動できるようになります。


  1. R 4.4.0からはdata.frame()関数で利用される引数として、stringsAsFactors = FALSEがデフォルトになりました。これにより、文字列型のデータがデフォルトでfactors型に変換されなくなりました。 そのため、古いバージョンのRで書かれたコードを新しいバージョンのRで実行すると、データの型が変わる可能性があります。↩︎

  2. R 3.6.0から、乱数生成アルゴリズムが変更されました。↩︎