class RailsDataExplorer::Chart::Scatterplot
Responsibilities:
* Render a scatter plot for either * bivariate analysis of two quantitative data series or * multivariate analysis of two quantitative and one categorical data series.
Collaborators:
* DataSet
Public Class Methods
new(_data_set, options = {})
click to toggle source
# File lib/rails_data_explorer/chart/scatterplot.rb, line 16 def initialize(_data_set, options = {}) @data_set = _data_set @options = {}.merge(options) end
Public Instance Methods
compute_chart_attrs()
click to toggle source
# File lib/rails_data_explorer/chart/scatterplot.rb, line 21 def compute_chart_attrs x_candidates = @data_set.data_series.find_all { |ds| (ds.chart_roles[Chart::Scatterplot] & [:x, :any]).any? } y_candidates = @data_set.data_series.find_all { |ds| (ds.chart_roles[Chart::Scatterplot] & [:y, :any]).any? } color_candidates = @data_set.data_series.find_all { |ds| (ds.chart_roles[Chart::Scatterplot] & [:color, :any]).any? } size_candidates = @data_set.data_series.find_all { |ds| (ds.chart_roles[Chart::Scatterplot] & [:size, :any]).any? } x_ds = x_candidates.first y_ds = (y_candidates - [x_ds]).first color_ds = (color_candidates - [x_ds, y_ds]).first size_ds = (size_candidates - [x_ds, y_ds, color_ds]).first return false if x_ds.nil? || y_ds.nil? ca = case @data_set.dimensions_count when 0,1 raise(ArgumentError.new("At least two data series required for scatterplot, only #{ @data_set.dimensions_count } given")) when 2 key = '' values_hash = x_ds.values.length.times.map { |idx| r = { x: x_ds.values[idx], y: y_ds.values[idx] } r[:color] = color_ds.values[idx] if color_ds r } { values: values_hash, x_axis_label: x_ds.name, x_axis_tick_format: x_ds.axis_tick_format, y_axis_label: y_ds.name, y_axis_tick_format: y_ds.axis_tick_format, } when 3 visual_attr_ds = color_ds || size_ds raise "No visual_attr_ds given" if visual_attr_ds.nil? data_series_hash = visual_attr_ds.values.uniq.inject({}) { |m,visual_attr| m[visual_attr] = [] m } x_ds.values.length.times.each { |idx| data_series_hash[visual_attr_ds.values[idx]] << { x: x_ds.values[idx], y: y_ds.values[idx] } } { values: data_series_hash, x_axis_label: x_ds.name, x_axis_tick_format: x_ds.axis_tick_format, y_axis_label: y_ds.name, y_axis_tick_format: y_ds.axis_tick_format, } else end ca end
render()
click to toggle source
# File lib/rails_data_explorer/chart/scatterplot.rb, line 80 def render return '' unless render? ca = compute_chart_attrs return '' unless ca render_vega(ca) end
render_nvd3(ca)
click to toggle source
# File lib/rails_data_explorer/chart/scatterplot.rb, line 183 def render_nvd3(ca) %( <div class="rde-chart rde-scatterplot"> <h3 class="rde-chart-title">Scatterplot</h3> <div id="#{ dom_id }", style="height: 400px;"> <svg></svg> </div> <script type="text/javascript"> (function() { var data = #{ ca[:values].to_json }; nv.addGraph(function() { var chart = nv.models.scatterChart() .showDistX(true) .showDistY(true) .useVoronoi(true) .color(d3.scale.category10().range()) .transitionDuration(300) ; chart.xAxis.tickFormat(#{ ca[:x_axis_tick_format] }) .axisLabel('#{ ca[:x_axis_label] }') ; chart.yAxis.tickFormat(#{ ca[:y_axis_tick_format] }) .axisLabel('#{ ca[:y_axis_label] }') ; chart.tooltipContent(function(key) { return key; }); d3.select('##{ dom_id } svg') .datum(data) .call(chart); nv.utils.windowResize(chart.update); chart.dispatch.on('stateChange', function(e) { ('New State:', JSON.stringify(e)); }); return chart; }); })(); </script> </div> ) end
render_vega(ca)
click to toggle source
# File lib/rails_data_explorer/chart/scatterplot.rb, line 87 def render_vega(ca) %( <div class="rde-chart rde-scatterplot"> <h3 class="rde-chart-title">Scatterplot</h3> <div id="#{ dom_id }"></div> <script type="text/javascript"> (function() { var spec = { "width": 960, "height": 200, "data": [ { "name": "table", "values": #{ ca[:values].to_json } }, ], "scales": [ { "name": "x", "nice": true, "range": "width", "zero": false, "domain": {"data": "table", "field": "data.x"} }, { "name": "y", "nice": true, "range": "height", "zero": false, "domain": {"data": "table", "field": "data.y"} }, // { // "name": "c", // "type": "ordinal", // "domain": {"data": "iris", "field": "data.species"}, // "range": ["#800", "#080", "#008"] // } ], "axes": [ { "type": "x", "scale": "x", "offset": 5, "title": "#{ ca[:x_axis_label] }", }, { "type": "y", "scale": "y", "offset": 5, "title": "#{ ca[:y_axis_label] }", } ], // "legends": [ // { // "fill": "c", // "title": "Species", // "offset": 0, // "properties": { // "symbols": { // "fillOpacity": {"value": 0.5}, // "stroke": {"value": "transparent"} // } // } // } // ], "marks": [ { "type": "symbol", "from": {"data": "table"}, "properties": { "enter": { "x": {"scale": "x", "field": "data.x"}, "y": {"scale": "y", "field": "data.y"}, //"fill": {"scale": "c", "field": "data.species"}, "fill": { "value": "#1F77B4" }, "fillOpacity": {"value": 0.4}, }, "update": { "size": {"value": 30}, "stroke": {"value": "transparent"} }, } } ] }; vg.parse.spec(spec, function(chart) { var view = chart({ el:"##{ dom_id }" }).update(); }); })(); </script> </div> ) end