LoginSignup
5
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-02-22

はじめに

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

PyPlotでは

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

import matplotlib.pyplot as plt

plt.plot([4,6,5,7,8,1])
plt.show()

Unknown.png

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

require 'rbplot'

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

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

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

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

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

使い方は以下のとおり。

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

スクリーンショット 2017-02-22 15.08.22.png

できた!

二本の線を描くには

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

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

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

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

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

できた!

グラフのタイトルを追加

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

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

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

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

できた!

最終的に...

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

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

どう?(^-^)

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

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2