ruby-numo / numo-gnuplot

Gnuplot wrapper for Ruby/Numo
BSD 3-Clause "New" or "Revised" License
51 stars 8 forks source link

support Daru::Vector Daru::DataFrame #14

Closed kojix2 closed 7 years ago

kojix2 commented 7 years ago

I do not know whether Numo should support Sciruby classes such as Daru::Vector, Daru::DataFrame.

But I'm glad if Numo-gnuplot plot supports Daru::Vector.

df = Daru::DataFrame.from_csv "hoge.csv"

N.noteplot do
  plot df.x, df.y
  # I do not want to convert it to RubyArray
  # plot df.x.to_a, df.y.to_a 
end
masa16 commented 7 years ago

Fixed to support your proposed feature: https://github.com/ruby-numo/gnuplot/commit/350ad7f4a90d2baccc5ed3a075fccc50af9e2fe8

kojix2 commented 7 years ago

Thank you very much for your response. The plot method worked as expected.

require 'numo/gnuplot'
require 'daru'

df = Daru::DataFrame.from_csv 'iris.csv'

iris_dfs = df.Name.uniq.to_a.map { |name| df.where(df.Name.eq name) }
# [DetaFrame(setosa), DataFrame(versicolor), DataFrame(virginica)]

Numo.gnuplot do
  set title: 'The Iris DataSet'
  set xlabel: 'sepal length'
  set ylabel: 'sepal width'
  set zlabel: 'petal width'
  fuga = iris_dfs.map do |df|
    [df.SepalLength, df.SepalWidth,
     w: :points, pt: 6, lw: 3, t: df.Name[0]]
  end
  plot *fuga
end

iris_2d

However, the splot method does not work. I tried modifying the SPlotRecord class ad hoc.

  # @private
  class SPlotRecord < PlotData  # :nodoc: all

    def initialize(x,y,z)
      @text = false
      @data = [x,y,z].map{|a| a.respond_to?(:flatten) ? a.flatten : a.to_a}
      @n = @data.map{|a| a.size}.min
      shape = PlotData.array_shape(z.respond_to?(:flatten) ? z : z.to_a)

It worked.

require 'numo/gnuplot'
require 'daru'

df = Daru::DataFrame.from_csv 'iris.csv'

iris_dfs = df.Name.uniq.to_a.map { |name| df.where(df.Name.eq name) }
# [DetaFrame(setosa), DataFrame(versicolor), DataFrame(virginica)]

Numo.gnuplot do
  set title: 'The Iris DataSet'
  set xlabel: 'sepal length'
  set ylabel: 'sepal width'
  set zlabel: 'petal width'
  fuga = iris_dfs.map do |df|
    [df.SepalLength, df.SepalWidth, df.PetalWidth,
     w: :points, pt: 6, lw: 3, t: df.Name[0]]
  end
  splot *fuga
end

iris3d

Please fix splot in your better way. Thank you.

kojix2 commented 7 years ago

Thank you very much. The splot method of the iris script above works as expected. But Please help me a little more.. Compatiblity with Numo::NArray.

test script

require 'numo/narray' # as I always do
require 'numo/gnuplot'
require 'daru'

a = Daru::Vector[1,2,3]

Numo.gnuplot { splot a, a, a }

This is the error message.

Numo::NArray::CastError: unknown conversion from Daru::Vector to Numo::DFloat
from ... /gems/numo-gnuplot-0.2.3/lib/numo/gnuplot.rb:866:in `[]='

gnuplot.rb:866

    def data_str
      if @text
        s = ""
        @n.times{|i| s << line_str(i)+"\n"}
        s + "e\n"
      elsif defined? Numo::NArray
        m = @data.size
        x = Numo::DFloat.zeros(@n,m)
        m.times{|i| x[true,i] = @data[i][0...@n]} # Here is line 866.
        x.to_string
      else
        s = []
        @n.times{|i| s.concat @data.map{|a| a[i]}}
        s.pack("d*")
      end
    end

@data[i] and @data[i][0...@n] are the same.

p @data[i][0...@n]
#<Daru::Vector(3)>
#   0   1
#   1   2
#   2   3
kojix2 commented 7 years ago

Finally, I can easily draw graphs using Daru and gnuplot. Very useful. Thank you very much.