Class: Rubyvis::Flatten
Overview
Represents a flatten operator for the specified array. Flattening allows hierarchical maps to be flattened into an array. The levels in the input tree are specified by key functions.
For example, consider the following hierarchical data structure of Barley yields, from various sites in Minnesota during 1931-2:
{ 1931: {
Manchuria: {
"University Farm": 27.00,
"Waseca": 48.87,
"Morris": 27.43,
... },
Glabron: {
"University Farm": 43.07,
"Waseca": 55.20,
... } },
1932: {
... } }
To facilitate visualization, it may be useful to flatten the tree into a tabular array:
var array = pv.flatten(yields)
.key("year")
.key("variety")
.key("site")
.key("yield")
.array();
This returns an array of object elements. Each element in the array has attributes corresponding to this flatten operator's keys:
{ site: "University Farm", variety: "Manchuria", year: 1931, yield: 27 },
{ site: "Waseca", variety: "Manchuria", year: 1931, yield: 48.87 },
{ site: "Morris", variety: "Manchuria", year: 1931, yield: 27.43 },
{ site: "University Farm", variety: "Glabron", year: 1931, yield: 43.07 },
{ site: "Waseca", variety: "Glabron", year: 1931, yield: 55.2 }, ...
The flatten operator is roughly the inverse of the pv.Nest and pv.Tree operators.
Instance Method Summary collapse
-
#array ⇒ Object
(also: #to_a)
Returns the flattened array.
-
#initialize(map) ⇒ Flatten
constructor
A new instance of Flatten.
-
#key(k, f = nil) ⇒ Object
Flattens using the specified key function.
-
#leaf(f) ⇒ Object
Flattens using the specified leaf function.
- #recurse(value, i) ⇒ Object
- #visit(value, i) ⇒ Object
Constructor Details
#initialize(map) ⇒ Flatten
Returns a new instance of Flatten.
50 51 52 53 54 |
# File 'lib/rubyvis/flatten.rb', line 50 def initialize(map) @map=map @keys=[] @leaf=nil end |
Instance Method Details
#array ⇒ Object Also known as: to_a
Returns the flattened array. Each entry in the array is an object; each object has attributes corresponding to this flatten operator's keys.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/rubyvis/flatten.rb', line 107 def array @entries=[] @stack=[] if @leaf recurse(@map,0) return @entries end visit(@map,0) @entries.map {|stack| m={} @keys.each_with_index {|k,i| v=stack[i] m[k.name]=k.value ? k.value.js_call(self,v) : v } m } end |
#key(k, f = nil) ⇒ Object
Flattens using the specified key function. Multiple keys may be added to the flatten; the tiers of the underlying tree must correspond to the specified keys, in order. The order of the returned array is undefined; however, you can easily sort it.
64 65 66 67 68 |
# File 'lib/rubyvis/flatten.rb', line 64 def key(k, f=nil) @keys.push(OpenStruct.new({:name=>k, :value=>f})) @leaf=nil self end |
#leaf(f) ⇒ Object
Flattens using the specified leaf function. This is an alternative to
specifying an explicit set of keys; the tiers of the underlying tree
will be determined dynamically by recursing on the values, and the resulting keys will be stored in the entries :keys attribute. The leaf function must return true for leaves, and false for internal nodes.
76 77 78 79 80 |
# File 'lib/rubyvis/flatten.rb', line 76 def leaf(f) @keys.clear @leaf=f self end |
#recurse(value, i) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/rubyvis/flatten.rb', line 81 def recurse(value,i) if @leaf.call(value) @entries.push({:keys=>@stack.dup, :value=>value}) else value.each {|key,v| @stack.push(key) recurse(v, i+1) @stack.pop } end end |
#visit(value, i) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/rubyvis/flatten.rb', line 92 def visit(value,i) if (i < @keys.size - 1) value.each {|key,v| @stack.push(key) visit(v,i+1) @stack.pop } else @entries.push(@stack+[value]) end end |