This class implements a grouping data structure for Ruport. A grouping is a collection of groups. It allows you to group the data in a table by one or more columns that you specify.
The data for a grouping is a hash of groups, keyed on each unique data point from the grouping column.
Creates a new Grouping based on the supplied options.
Valid options:
:by |
A column name or array of column names that the data will be grouped on. |
:order |
Determines the iteration and presentation order of a Grouping object. Set to :name to order by Group names. You can also provide a lambda which will be passed Group objects, and use semantics similar to Enumerable#group_by |
Examples:
table = [[1,2,3],[4,5,6],[1,1,2]].to_table(%w[a b c]) # unordered grouping = Grouping.new(table, :by => "a") # ordered by group name grouping = Grouping.new(table, :by => "a", :order => :name) # ordered by group size grouping = Grouping.new(table, :by => "a", :order => lambda { |g| g.size } )
# File lib/ruport/data/grouping.rb, line 164 def initialize(data={},options={}) if data.kind_of?(Hash) @grouped_by = data[:by] @order = data[:order] @data = {} else @grouped_by = options[:by] @order = options[:order] cols = Array(options[:by]).dup @data = data.to_group.send(:grouped_data, cols.shift) cols.each do |col| @data.each do |name,group| group.send(:create_subgroups, col) end end end end
Used to add extra data to the Grouping. group should be a Group.
Example:
table = [[1,2,3],[4,5,6]].to_table(%w[a b c]) grouping = Grouping.new(table, :by => "a") group = Group.new :name => 7, :data => [[8,9]], :column_names => %w[b c] grouping << group
# File lib/ruport/data/grouping.rb, line 245 def <<(group) if data.has_key? group.name raise(ArgumentError, "Group '#{group.name}' exists!") end @data.merge!({ group.name => group }) end
Allows Hash-like indexing of the grouping data.
Examples:
my_grouping["foo"]
# File lib/ruport/data/grouping.rb, line 194 def [](name) @data[name] or raise(IndexError,"Group Not Found") end
Iterates through the Grouping, yielding each group name and Group object
# File lib/ruport/data/grouping.rb, line 201 def each if @order.respond_to?(:call) @data.sort_by { |n,g| @order[g] }.each { |n,g| yield(n,g) } elsif @order == :name @data.sort_by { |n,g| n }.each { |name,group| yield(name,group) } else @data.each { |name,group| yield(name,group) } end end
Provides a shortcut for the as() method by converting a call to to_format_name into a call to as(:format_name).
# File lib/ruport/data/grouping.rb, line 367 def method_missing(id,*args) return as($1.to_sym,*args) if id.to_s =~ /^to_(.*)/ super end
Calculates sums. If a column name or index is given, it will try to convert each element of that column to an integer or float and add them together. The sum is calculated across all groups in the grouping.
If a block is given, it yields each Record in each Group so that you can do your own calculation.
Example:
table = [[1,2,3],[3,4,5],[5,6,7]].to_table(%w[col1 col2 col3]) grouping = Grouping(table, :by => "col1") grouping.sigma("col2") #=> 12 grouping.sigma(0) #=> 12 grouping.sigma { |r| r.col2 + r.col3 } #=> 27 grouping.sigma { |r| r.col2 + 1 } #=> 15
# File lib/ruport/data/grouping.rb, line 329 def sigma(column=nil) inject(0) do |s, (group_name, group)| if column s + group.sigma(column) else s + group.sigma do |r| yield(r) end end end end
Returns a new grouping with the specified sort order. You can sort by Group name or an arbitrary block
by_name = grouping.sort_grouping_by(:name) by_size = grouping.sort_grouping_by { |g| g.size }
# File lib/ruport/data/grouping.rb, line 217 def sort_grouping_by(type=nil,&block) a = Grouping.new(:by => @grouped_by, :order => type || block) each { |n,g| a << g } return a end
Applies the specified sort order to an existing Grouping object.
grouping.sort_grouping_by!(:name) grouping.sort_grouping_by! { |g| g.size }
# File lib/ruport/data/grouping.rb, line 227 def sort_grouping_by!(type=nil,&block) @order = type || block end
Provides access to the subgroups of a particular group in the Grouping. Supply the name of a group and it returns a Grouping created from the subgroups of the group.
# File lib/ruport/data/grouping.rb, line 258 def subgrouping(name) grouping = dup grouping.send(:data=, @data[name].subgroups) return grouping end
Useful for creating basic summaries from Grouping objects. Takes a field to summarize on, and then for each group, runs the specified procs and returns the results as a Table.
The following example would show for each date group, the sum for the attributes or methods :opened and :closed and order them by the :order array.
If :order is not specified, you cannot depend on predictable column order.
grouping.summary :date, :opened => lambda { |g| g.sigma(:opened) }, :closed => lambda { |g| g.sigma(:closed) }, :order => [:date,:opened,:closed]
# File lib/ruport/data/grouping.rb, line 282 def summary(field,procs) if procs[:order].kind_of?(Array) cols = procs.delete(:order) else cols = procs.keys + [field] end expected = Table(cols) { |t| each do |name,group| t << procs.inject({field => name}) do |s,r| s.merge(r[0] => r[1].call(group)) end end t.data.reorder(cols) } end
Uses Ruport's built-in text formatter to render this Grouping
Example:
table = [[1,2,3],[4,5,6]].to_table(%w[a b c]) grouping = Grouping.new(table, :by => "a") puts grouping.to_s
# File lib/ruport/data/grouping.rb, line 308 def to_s as(:text) end
Generated with the Darkfish Rdoc Generator 2.