Class: Rubyvis::Nest

Inherits:
Object show all
Defined in:
lib/rubyvis/nest.rb

Overview

Represents a Nest operator for the specified array. Nesting allows elements in an array to be grouped into a hierarchical tree structure. The levels in the tree are specified by key functions. The leaf nodes of the tree can be sorted by value, while the internal nodes can be sorted by key. Finally, the tree can be returned either has a multidimensional array via Nest.entries, or as a hierarchical map via Nest.map. The Nest.rollup routine similarly returns a map, collapsing the elements in each leaf node using a summary function.

For example, consider the following tabular data structure of Barley yields, from various sites in Minnesota during 1931-2:

{ yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm" },
{ yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca" },
{ yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris" }

To facilitate visualization, it may be useful to nest the elements first by year, and then by variety, as follows:

var nest = Rubyvis.nest(yields)
.key(lambda {|d|  d.year})
.key(lambda {|d| d.variety})
.entries();

This returns a nested array. Each element of the outer array is a key-values pair, listing the values for each distinct key:

<pre>{ key: 1931, values: [

{ key: "Manchuria", values: [
    { yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm" },
    { yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca" },
    { yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris" },
    ...
  ] },
{ key: "Glabron", values: [
    { yield: 43.07, variety: "Glabron", year: 1931, site: "University Farm" },
    { yield: 55.20, variety: "Glabron", year: 1931, site: "Waseca" },
    ...
  ] },
] },

{ key: 1932, values: … }</pre>

Further details, including sorting and rollup, is provided below on the corresponding methods.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(array) ⇒ Nest

Constructs a nest operator for the specified array. This constructor should not be invoked directly; use Rubyvis.nest instead.



76
77
78
79
80
# File 'lib/rubyvis/nest.rb', line 76

def initialize(array)
  @array=array
  @keys=[]
  @order=nil
end

Instance Attribute Details

#arrayObject

Returns the value of attribute array.



71
72
73
# File 'lib/rubyvis/nest.rb', line 71

def array
  @array
end

#keysObject

Returns the value of attribute keys.



71
72
73
# File 'lib/rubyvis/nest.rb', line 71

def keys
  @keys
end

#orderObject

Returns the value of attribute order.



71
72
73
# File 'lib/rubyvis/nest.rb', line 71

def order
  @order
end

Instance Method Details

#entriesObject



119
120
121
# File 'lib/rubyvis/nest.rb', line 119

def entries()
  entries_sort(entries_entries(map),0)
end

#entries_entries(map) ⇒ Object



122
123
124
125
126
127
128
# File 'lib/rubyvis/nest.rb', line 122

def entries_entries(map)
  array=[]
  map.each_pair {|k,v|
    array.push(NestedArray.new({:key=>k, :values=>(v.is_a? Array) ? v: entries_entries(v)}))
  }
  array
end

#entries_sort(array, i) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/rubyvis/nest.rb', line 129

def entries_sort(array,i)
  o=keys[i].order
  if o
    array.sort! {|a,b| o.call(a.key, b.key)}
  end
  i+=1
  if (i<keys.size)
    array.each {|v|
      entries_sort(v, i)
    }
  end
  array
  
end

#key(k) ⇒ Object



81
82
83
84
# File 'lib/rubyvis/nest.rb', line 81

def key(k)
  @keys.push(k)
  return self
end

#mapObject



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/rubyvis/nest.rb', line 93

def map
  #i=0
  map={} 
  values=[]
  @array.each_with_index {|x,j|
    m=map
    (@keys.size-1).times {|i|
      k=@keys[i].call(x)
      m[k]={} if (!m[k])
      m=m[k]
    }
    k=@keys.last.call(x)
    if(!m[k])
      a=[]
      values.push(a)
      m[k]=a
    end
    m[k].push(x)
  }
  if(self.order)
    values.each_with_index {|v,vi|
      values[vi].sort!(&self.order)
    }
  end
  map
end

#rollup(f) ⇒ Object



153
154
155
# File 'lib/rubyvis/nest.rb', line 153

def rollup(f)
  rollup_rollup(self.map,f)
end

#rollup_rollup(map, f) ⇒ Object



143
144
145
146
147
148
149
150
151
152
# File 'lib/rubyvis/nest.rb', line 143

def rollup_rollup(map,f)
  map.each_pair {|key,value|
    if value.is_a? Array
      map[key]=f.call(value)
    else
      rollup_rollup(value)
    end
  }
  return map;
end

#sort_keys(order = nil) ⇒ Object



85
86
87
88
# File 'lib/rubyvis/nest.rb', line 85

def sort_keys(order=nil)
  keys[keys.size-1].order = order.nil? ? Rubyvis.natural_order : order
  return self
end

#sort_values(order = nil) ⇒ Object



89
90
91
92
# File 'lib/rubyvis/nest.rb', line 89

def sort_values(order=nil)
  @order = order.nil? ? Rubyvis.natural_order : order
  return self
end