# -*- coding: utf-8 -*- class RailsDataExplorer class Chart # Responsibilities: # * Render a stacked bar chart for bivariate analysis of two categorical # data series. Renders absolute frequencies of y-data series. # # Collaborators: # * DataSet # class StackedBarChartCategorical < Chart def initialize(_data_set, options = {}) @data_set = _data_set @options = {}.merge(options) end def compute_chart_attrs val_mod = { name: :limit_distinct_values } x_candidates = @data_set.data_series.find_all { |ds| (ds.chart_roles[Chart::StackedBarChartCategoricalPercent] & [:x, :any]).any? }.sort { |a,b| b.uniq_vals_count(val_mod) <=> a.uniq_vals_count(val_mod) } y_candidates = @data_set.data_series.find_all { |ds| (ds.chart_roles[Chart::StackedBarChartCategoricalPercent] & [:y, :any]).any? } x_ds = x_candidates.first y_ds = (y_candidates - [x_ds]).first return false if x_ds.nil? || y_ds.nil? # initialize data_matrix data_matrix = { _sum: { _sum: 0 } } x_ds.uniq_vals(val_mod).each { |x_val| data_matrix[x_val] = {} data_matrix[x_val][:_sum] = 0 y_ds.uniq_vals(val_mod).each { |y_val| data_matrix[x_val][y_val] = 0 data_matrix[:_sum][y_val] = 0 } } # populate data_matrix x_ds.values(val_mod).length.times { |idx| x_val = x_ds.values(val_mod)[idx] y_val = y_ds.values(val_mod)[idx] data_matrix[x_val][y_val] += 1 data_matrix[:_sum][y_val] += 1 data_matrix[x_val][:_sum] += 1 data_matrix[:_sum][:_sum] += 1 } x_sorted_keys = x_ds.uniq_vals(val_mod).sort( &x_ds.label_sorter( nil, lambda { |a,b| data_matrix[b][:_sum] <=> data_matrix[a][:_sum] } ) ) y_sorted_keys = y_ds.uniq_vals(val_mod).sort( &y_ds.label_sorter( nil, lambda { |a,b| data_matrix[:_sum][b] <=> data_matrix[:_sum][a] } ) ) values = case @data_set.dimensions_count when 2 y_sorted_keys.map { |y_val| x_sorted_keys.map { |x_val| { x: x_val, y: compute_y_value(data_matrix, x_val, y_val), c: y_val } } }.flatten else raise(ArgumentError.new("Exactly two data series required for contingency table.")) end { values: values, x_axis_label: x_ds.name, x_axis_tick_format: 'function(d) { return d }', y_axis_label: compute_y_axis_label(y_ds.name), y_axis_tick_format: "d3.format('.1%')", } end # Override this method to change how the y value is computed. E.g., to # change from absolute values to percentages. def compute_y_value(data_matrix, x_val, y_val) data_matrix[x_val][y_val] end # @param y_ds_name [String] name of the y data series def compute_y_axis_label(y_ds_name) "Frequency" end def render return '' unless render? ca = compute_chart_attrs return '' unless ca render_vega(ca) end def render_vega(ca) %(

Stacked Bar Chart

) end def render_nvd3(ca) %(

Stacked Bar Chart

) end end end end