charty icon indicating copy to clipboard operation
charty copied to clipboard

Stop instance_eval in RenderContext

Open kou opened this issue 5 years ago • 1 comments

The following code doesn't work with the current instance_eval based implementation.

require "charty"

class MyApp
  def initialize
    @dataset = [
      [[1, 2, 3], [4, 2, 1]],
      [[1, 2, 3], [1, 5, 8]],
    ]
  end

  def run
    plotter = Charty::Plotter.new(:google_chart)
    figure = plotter.curve do
      @dataset.each do |data|
        series data[0], data[1]
      end
    end
    puts figure.render
  end
end

MyApp.new.run

Because @dataset.each do is evaluated in RenderContext. It should be evaluated in MyApp context.

kou avatar Oct 03 '19 03:10 kou

I'm designing the new plotting API.

One of the candidates is following holoviews' overlay system, which uses * operator to overlay two or more plots. In this API, the above example can be written in the code below.

figure = @datasets.map {|data| Charty.line_plot(data[0], data[1]) }.inject(:*)
figure.render

Or, the other candidate is following matplotlib's convention, which reuses the axes object.

figure = @datasets.inject(nil) do |figure, data|
  Charty.line_plot(data[0], data[1], figure: figure)
end
figure.render

This can be written in a more procedural programming style.

figure = nil
@datasets.each do |data|
  figure = Charty.line_plot(data[0], data[1], figure: figure)
end
figure.render

Moreover, I think we should support plotting by tidy table data like seaborn.

table = {
  x: @dataset.map(&:first).flatten,
  y: @dataset.map(&:last).flatten,
  row: @dataset.map.with_index {|row, i| [i] * row[0].length }.flatten
}
figure = Charty.line_plot(:x, :y, color: :row, data: table)

@kou, which do you like?

mrkn avatar Oct 07 '19 08:10 mrkn