iRubyでPyPlotっぽくグラフを描けるようにしたい！

# はじめに

iRubyでデータ分析をすることが増えてきたので、グラフを描画できないことにより致命的に困っています。
これまでPython(jupyter)でデータ分析を行ってきたことから、PyPlotのようなライブラリがあればいいなと思ったので、同じことができるようにクラスを作ってみました。

# PyPlotでは

以下のような方法でグラフが描画できます。

```py3:
import matplotlib.pyplot as plt

plt.plot([4,6,5,7,8,1])
plt.show()
```
![Unknown.png](https://qiita-image-store.s3.amazonaws.com/0/114240/314ebcbd-9f01-aa11-c242-dbce1d9e981f.png)

なので、同じようにするならこんな感じでできないかなと...

```rb:
require 'rbplot'

plt = RbPlot.new()
plt.plot([4,6,5,7,8,1])
plt.show()
```

# RbPlotというクラスを作ってみる

先日、gnuplotを使えばiRubyの中でグラフを表示できるようになるということがわかったので、これを利用することにします。

必要最低限のものを作ってみると以下のとおり。

```rb:
class RbPlot
  
  def initialize()
    @data = []
  end
    
  def plot(data)
    @data = data
  end

  def show()
    
    IRuby.display make(), mime: 'image/svg+xml'

  end
  
  def make()
    
    Gnuplot.open do |gp|
      
      Gnuplot::Plot.new( gp ) do |myplot|
        
        myplot.terminal "svg"
        
        myplot.data << Gnuplot::DataSet.new(@data) do |ds|
          ds.with = "lines"
          ds.notitle
        end
        
      end
      
    end
    
  end
  
end
```

使い方は以下のとおり。

```rb:
plt = RbPlot.new
plt.plot([4,6,5,7,8,1])
plt.show()
```

![スクリーンショット 2017-02-22 15.08.22.png](https://qiita-image-store.s3.amazonaws.com/0/114240/613c5afd-e3c4-0258-3914-e0bffd6dacc4.png)

できた！

# 二本の線を描くには

PyPlotでは、以下のように記述すると描画できます。

```py3:
import matplotlib.pyplot as plt

plt.plot([4,6,5,7,8,1])
plt.plot([2,4,3,6,5,9])
plt.show()
```

![Unknown.png](https://qiita-image-store.s3.amazonaws.com/0/114240/7aab9981-ccb0-e596-8578-71e81692c56d.png)

...これは便利だ(-_-;)

では、同じようにできるよう先ほどのクラスを改造してみます。

```rb:
class RbPlot2
  
  def initialize()
    @datas = []
  end
    
  def plot(data)
    @datas << data
  end

  def show()
    
    IRuby.display make(), mime: 'image/svg+xml'

  end
  
  def make()
    
    Gnuplot.open do |gp|
      
      Gnuplot::Plot.new( gp ) do |myplot|
        
        myplot.terminal "svg"
        
        @datas.each do |data|
          
          myplot.data << Gnuplot::DataSet.new(data) do |ds|
            ds.with = "lines"
            ds.notitle
          end
        
        end
          
      end
      
    end
    
  end
  
end
```
![スクリーンショット 2017-02-22 15.19.51.png](https://qiita-image-store.s3.amazonaws.com/0/114240/720e8110-ff28-df96-9a42-f2ab73bcea50.png)

できた！

# グラフのタイトルを追加

PyPlotでタイトルを表示しようとすると以下のとおりです。

```py3:
import matplotlib.pyplot as plt

plt.title("PyPlot")
plt.plot([4,6,5,7,8,1])
plt.plot([2,4,3,6,5,9])
plt.show()
```
![Unknown.png](https://qiita-image-store.s3.amazonaws.com/0/114240/aa813056-1e9f-6827-c66c-8e099b31c939.png)

これもできるようにしてみます。

```rb:
class RbPlot
  
  def initialize()
    @datas = []
    @title = ""
  end
    
  def title(title)
    @title = title
  end
  
  def plot(data)
    @datas << data
  end

  def show()
    IRuby.display make(), mime: 'image/svg+xml'
  end
  
  def make()
    Gnuplot.open do |gp|
      Gnuplot::Plot.new( gp ) do |myplot|
        myplot.terminal "svg"
        myplot.title @title
        @datas.each do |data|
          myplot.data << Gnuplot::DataSet.new(data) do |ds|
            ds.with = "lines"
            ds.notitle
          end
        end
      end
    end
  end
  
end
```
![スクリーンショット 2017-02-22 15.26.16.png](https://qiita-image-store.s3.amazonaws.com/0/114240/5b283c3c-0594-a249-618c-203de6bdeff4.png)

できた！

# 最終的に...

その後もごにょごにょいじっていたら、それなりにできた！

```rb:
require 'gnuplot'

class RbPlot
  
  def initialize()
    
    @arbitrary_lines = []
    @arbitrary_lines << "set terminal svg"
    
    @datas = []
    
  end
  
  def title(title)
    @arbitrary_lines << "set title '#{title}'"
  end
  
  def xlabel(xlabel)
    @arbitrary_lines << "set xlabel '#{xlabel}'"
  end

  def ylabel(ylabel)
    @arbitrary_lines << "set ylabel '#{ylabel}'"
  end
  
  def xlim(min, max)
    @arbitrary_lines << "set xrange [#{min}:#{max}]"
  end
  
  def ylim(min, max)
    @arbitrary_lines << "set yrange [#{min}:#{max}]"
  end
  
  def arbitrary_lines(value)
    @arbitrary_lines << "set " + value
  end
  
  def plot(value)
    @datas << {
      "type" => "lines",
      "value" => value
    }
  end
  
  def scatter(value)
    @datas << {
      "type" => "circles",
      "value" => value
    }
  end
  
  def show()
    IRuby.display make(), mime: 'image/svg+xml'
  end
    
  def make()
  
    Gnuplot.open do |gp|
      Gnuplot::Plot.new( gp ) do |myplot|
        @arbitrary_lines.each do |value|
          myplot.arbitrary_lines << value
        end
        @datas.each do |data|
          @with = data["type"]
          myplot.data << Gnuplot::DataSet.new(data["value"]) do |ds|
            ds.with = @with
            ds.notitle
          end
        end
      end
    end
    
  end
  
end

plt = RbPlot.new

x = [ 1, 3, 9]
y = [10,-2,-5]

plt.title("RbPlotテスト")
plt.ylabel("Y")
plt.xlabel("エックス")

plt.xlim(0,10)
plt.ylim(-10,20)

plt.arbitrary_lines("grid")

plt.plot([4,6,5,7,8,1])
plt.plot([2,4,3,6,5,9])
plt.plot([x,y])
plt.plot("x * x / 10")
plt.plot("10 * sin(x / 5 * 3.14)")

plt.show()
```
![スクリーンショット 2017-02-22 15.36.44.png](https://qiita-image-store.s3.amazonaws.com/0/114240/e5eb6dd1-64b7-5f04-7195-e90b85dd7a68.png)

どう？(^-^)

これで、それなりにiRubyでグラフが使えるようになった気がします。