Class: GroupedFrame

Inherits:
Object
  • Object
show all
Defined in:
lib/carray/frame/group.rb

Overview

GroupedFrame — the result of +CAFrame#group_by+ (memo §11.6, §16).

Holds the grouping categorical once (grouping is per-key, computed once and shared across every column). Three surfaces: grp["col"] -> the CArray group iterator (raw exposure) aggregate -> declarative per-column reductions into a new frame table { |g| }-> cross-column Ruby escape, g is a per-group view-frame

Instance Method Summary collapse

Constructor Details

#initialize(frame, cat, axis_name) ⇒ GroupedFrame

Returns a new instance of GroupedFrame.



59
60
61
62
63
64
# File 'lib/carray/frame/group.rb', line 59

def initialize(frame, cat, axis_name)
  @frame     = frame
  @cat       = cat
  @axis_name = axis_name
  @labels    = cat.labels          # group values, in code order
end

Instance Method Details

#[](name) ⇒ Object

Raw exposure: the CArray group iterator for one column (memo §11.6).



77
78
79
# File 'lib/carray/frame/group.rb', line 77

def [](name)
  @frame[name].group_by_category(@cat)
end

#aggregate(spec) ⇒ Object

Declarative aggregation (memo §11.6). Spec maps an output column name to +[input_column, reduction]+, where reduction is a Symbol (vectorized, applied through the group iterator) or a Proc (per-group custom, called with the group's column slice).



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/carray/frame/group.rb', line 85

def aggregate(spec)
  cols = {}
  spec.each do |out_name, (in_name, reduction)|
    out = out_name.to_s
    cols[out] =
      case reduction
      when Symbol
        self[in_name].public_send(reduction)
      when Proc
        per_group_column(in_name, reduction)
      else
        raise ArgumentError,
              "reduction must be a Symbol or Proc (got #{reduction.class})"
      end
  end
  CAFrame.new(cols, axis_name: @axis_name, index: label_index)
end

#inspectString

Returns:

  • (String)


132
133
134
# File 'lib/carray/frame/group.rb', line 132

def inspect
  "#<GroupedFrame ngroup=#{ngroup} by=#{@axis_name.inspect}>"
end

#labelsObject

Group key values (one per group), as an Array.



72
73
74
# File 'lib/carray/frame/group.rb', line 72

def labels
  @labels.dup
end

#ngroupObject

Number of groups.



67
68
69
# File 'lib/carray/frame/group.rb', line 67

def ngroup
  @labels.size
end

#tableObject

Cross-column Ruby escape (memo §11.6). The block receives a per-group view-frame and returns a Hash of output-name => value; the values are collected column-wise across groups into a new frame.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/carray/frame/group.rb', line 106

def table
  collected = {}
  order = nil
  each_group_frame do |g|
    out = yield(g)
    unless out.is_a?(Hash)
      raise ArgumentError, "table block must return a Hash (got #{out.class})"
    end
    order ||= out.keys.map(&:to_s)
    out.each { |k, v| (collected[k.to_s] ||= []) << v }
  end
  cols = {}
  (order || []).each do |name|
    vals = collected[name]
    cols[name] = CArray.object(vals.size) { |i| vals[i] }
  end
  CAFrame.new(cols, axis_name: @axis_name, index: label_index)
end