Rubyでさまざまな確率分布の乱数を生成してヒストグラムを描いてみた

# はじめに
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/7c03a276-a9ad-97b9-6336-615784351091.png)

　さまざまな確率分布に従う乱数を作成して、ヒストグラムを描いてみたくなる日は誰にでもあると思います。

　大丈夫。いつだって、世界の素晴らしいプログラマ達が驚くべきライブラリを作ってくれています。たとえ有名ではないライブラリでも、見つけてちゃんと使ってあげると、魔法のようなことが簡単にできたりします。

　この記事では、素晴らしいRubyのライブラリを２つ紹介します。[Numo::GSL](https://github.com/ruby-numo/numo-gsl) と [Flammarion](https://github.com/zach-capalbo/flammarion)です。これらを使うことで、驚くほど簡単に乱数を生成してヒストグラムが描出できます。

# 準備編
インストールは若干面倒なので、飛ばして、最後までいったら戻ってきて見てください。

<details><summary>Numo::GSLとFlammarionをインストールする</summary><div>

## Numo::GSLをインストールする
[Numo::GSL](https://github.com/ruby-numo/numo-gsl) はGNU Scientific Library (GSL) のバインディングです。Ruby界にはGSLとのバインディングはいろいろありますがNArrayの利用を考えて私はこれを使っています。
　2019/5 現在、Numo::GSLは、GSL2.4以降に対応していません。なので、多くの環境ではソースコードからGSL2.3をインストールする必要があります。そんなわけで少し手間がかかりますが**それだけの価値はあります**。下記のような感じでコマンドを打てば大丈夫です。公式サイトの[ダウンロードページ](http://ftp.jaist.ac.jp/pub/GNU/gsl/)から、gsl-2.3.tar.gz をダウンロードします。
…と思いましたがUbuntuでは `sudo apt install libgsl23` するだけで大丈夫なこともあるようだ。

```bash
wget http://ftp.jaist.ac.jp/pub/GNU/gsl/gsl-2.3.tar.gz
tar -zxvf gsl-2.3.tar.gz
cd gsl-2.3
./configure
make -j4 # CPUコア数を指定

# checkinstallを使う場合
sudo checkinstall

# インストール場所を自分で指定する場合
# make DESTDIR=/path/you/want/to/install/ install
```

```bash
# Githubからnumo-gslを取得
git clone https://github.com/ruby-numo/numo-gsl
cd numo-gsl
rake build
gem install pkg/numo-gsl-0.1.2.gem # -- --with-gsl-lib=usr/local/lib

# GSLのインストール場所を自分で指定する場合
# gem install pkg/numo-gsl-0.1.2.gem -- --with-gsl-lib=/path/you/want/to/install/usr/local/lib
```

## Flammarionをインストールする
Rubyでグラフを表示する方法はたくさんあります。

しかし！ここではあえて誰も知らないマイナーな方法：**Flammarionを使ってplotyを使う** をやります。FlammarionはChromeとelectronによるGUIツールキットで面白い機能がたくさんついている素晴らしいツールです。Plotlyによるグラフ表示機能もその一つです。Flammarionについてはまた別の機会にエントリーを書きたいと思います。Flammarionの開発は継続していますが、やや更新が遅れているようです。我こそはと思う人はコントリビューションするとよいと思います。
https://github.com/zach-capalbo/flammarion

```bash
gem install flammarion
```
</div></detail>

`irb` または `pry` を立ち上げて、FlammarionとNumo::GSLを準備します。

```ruby
require 'flammarion'
require 'numo/gsl'
f = Flammarion::Engraving.new
r = Numo::GSL::Rng::Rand.new
```

ここから先は簡単です。

## 二項分布
```ruby
a = r.binomial(0.5, 100, 10000).to_a
f.plot(x: a, type: "histogram")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/e157190c-a633-4a33-e592-a0649fd2f754.png)

## ポアソン分布
```ruby
a = r.poisson(3, 10000).to_a
f.plot(x: a, type: "histogram")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/795773b9-7046-e617-5d7f-66b917f7ef32.png)

## ベルヌーイ分布
```ruby
a = r.bernoulli(0.3,10000).to_a
f.plot(x: a, type: "histogram",
       autobinx: false, xbins: {start:0, end:1.1, size: 0.1})
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/8ff8e0d3-1934-5ad4-a9c0-0dcb626320b4.png)

## 指数分布
```ruby
a = r.exponential(2,10000).to_a
f.plot(x: a, type: "histogram")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/2c7f5e0b-3c9d-d3a5-87a6-fef5e606bcc6.png)

## ガンマ分布
```ruby
a = r.gamma(5,1,10000).to_a
f.plot(x: a, type: "histogram")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/422278dc-915d-ba19-6f5a-61c74bcf1314.png)


## ベータ分布
```ruby
a = r.beta(0.5,0.5,10000).to_a
f.plot(x: a, type: "histogram")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/1b3f237f-9b22-2952-a18f-dd3cd2fc8c5f.png)

## 正規分布
```ruby
a = r.gaussian(0.2,10000).to_a
f.plot(x: a, type: "histogram")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/be4fccff-0f27-0720-22ae-4f251dac2026.png)

こんな感じで簡単にグラフが描けます。
GSLの関数が使えるので、だいたいの分布のヒストグラムは描けるのではないでしょうか。

Flammarionのテーブル機能を使って、rに登録されたメソッドの一覧を表示してみましょう。

```ruby
f.table( (r.methods - Object.methods).each_slice(5).to_a)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/3906ca0e-7eeb-4cf7-2bae-57ee99cc4420.png)

このようにいろいろと用意されていることがわかります。
なーんだ、Rubyでも簡単にできるじゃないか。

リファレンスや文献がすくなくて、探すのが大変なんですけどね。

この記事は以上です。