rubyvis 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.txt +8 -0
- data/Manifest.txt +45 -36
- data/examples/{first_rbp_api.rb → 1_basic/1a_bar_rbp_api.rb} +1 -1
- data/examples/{first_protovis_api.rb → 1_basic/1b_bar_pv_api.rb} +1 -1
- data/examples/{second.rb → 1_basic/2_bar_and_rule.rb} +2 -2
- data/examples/{third.rb → 1_basic/3_grouped_bars.rb} +1 -1
- data/examples/{area_interpolation.rb → 1_basic/area_interpolation.rb} +1 -1
- data/examples/{dot.rb → 1_basic/dot.rb} +1 -1
- data/examples/{fixtures → 1_basic/fixtures}/tipsy.gif +0 -0
- data/examples/1_basic/grid.rb +29 -0
- data/examples/{image.rb → 1_basic/image.rb} +1 -1
- data/examples/{line.rb → 1_basic/line.rb} +1 -1
- data/examples/{line_interpolation.rb → 1_basic/line_interpolation.rb} +1 -1
- data/examples/2_medium/censo_agropecuario/censo_agropecuario_chile_data.rb +53 -0
- data/examples/2_medium/censo_agropecuario/census_treemap.rb +63 -0
- data/examples/2_medium/censo_agropecuario/create_data.rb +10 -0
- data/examples/2_medium/censo_agropecuario/resultset.csv +51 -0
- data/examples/{nested_grid.rb → 2_medium/nested_grid.rb} +3 -4
- data/examples/{area.rb → 3_pv_conventional/area.rb} +1 -1
- data/examples/{bar_column_chart.rb → 3_pv_conventional/bar_column_chart.rb} +1 -1
- data/examples/{grouped_charts.rb → 3_pv_conventional/grouped_charts.rb} +1 -1
- data/examples/{line_and_step.rb → 3_pv_conventional/line_and_step.rb} +1 -1
- data/examples/{pie_and_donut.rb → 3_pv_conventional/pie_and_donut.rb} +1 -1
- data/examples/{scatterplot.rb → 3_pv_conventional/scatterplot.rb} +1 -1
- data/examples/{stacked_charts.rb → 3_pv_conventional/stacked_charts.rb} +1 -3
- data/examples/{antibiotics → 4_pv_custom/antibiotics}/antibiotics_data.rb +0 -0
- data/examples/{antibiotics → 4_pv_custom/antibiotics}/antibiotics_scatter.rb +1 -1
- data/examples/{antibiotics → 4_pv_custom/antibiotics}/antibiotics_wedge.rb +1 -1
- data/examples/{barley → 4_pv_custom/barley}/barley.rb +5 -1
- data/examples/{barley → 4_pv_custom/barley}/barley_data.rb +0 -0
- data/examples/{cars → 4_pv_custom/cars}/cars.rb +1 -1
- data/examples/{cars → 4_pv_custom/cars}/cars_data.rb +0 -0
- data/examples/{crimea → 4_pv_custom/crimea}/crimea_data.rb +0 -0
- data/examples/{crimea → 4_pv_custom/crimea}/crimea_grouped_bar.rb +1 -1
- data/examples/{crimea → 4_pv_custom/crimea}/crimea_line.rb +1 -1
- data/examples/{bubble_charts.rb → 5_pv_hierarchies/bubble_charts.rb} +3 -2
- data/examples/5_pv_hierarchies/bubble_charts_matrix.rb +64 -0
- data/examples/{circle_packing.rb → 5_pv_hierarchies/circle_packing.rb} +4 -4
- data/examples/{dendogram.rb → 5_pv_hierarchies/dendogram.rb} +2 -2
- data/examples/{icicle.rb → 5_pv_hierarchies/icicle.rb} +2 -2
- data/examples/{indent.rb → 5_pv_hierarchies/indent.rb} +2 -2
- data/examples/5_pv_hierarchies/node_link_tree.rb +52 -0
- data/examples/{sunburst.rb → 5_pv_hierarchies/sunburst.rb} +2 -2
- data/examples/5_pv_hierarchies/treemap.rb +48 -0
- data/lib/rubyvis.rb +1 -1
- data/lib/rubyvis/dom.rb +16 -1
- data/lib/rubyvis/internals.rb +2 -2
- data/lib/rubyvis/layout.rb +2 -0
- data/lib/rubyvis/layout/grid.rb +105 -0
- data/lib/rubyvis/layout/pack.rb +53 -54
- data/lib/rubyvis/layout/stack.rb +26 -24
- data/lib/rubyvis/layout/tree.rb +267 -0
- data/lib/rubyvis/layout/treemap.rb +1 -0
- data/lib/rubyvis/mark.rb +10 -8
- data/lib/rubyvis/mark/area.rb +6 -6
- data/lib/rubyvis/mark/dot.rb +1 -1
- data/lib/rubyvis/mark/shorcut_methods.rb +29 -2
- data/lib/rubyvis/nest.rb +48 -2
- data/lib/rubyvis/scale/ordinal.rb +6 -6
- data/lib/rubyvis/scale/quantitative.rb +13 -7
- data/lib/rubyvis/scene/svg_area.rb +20 -14
- data/lib/rubyvis/scene/svg_bar.rb +1 -1
- data/lib/rubyvis/scene/svg_scene.rb +0 -1
- data/lib/rubyvis/sceneelement.rb +1 -1
- data/spec/area_spec.rb +12 -0
- data/spec/dom_spec.rb +15 -8
- data/spec/layout_stack_spec.rb +70 -0
- data/spec/nest_spec.rb +8 -2
- data/spec/scale_linear_spec.rb +7 -1
- data/spec/scale_ordinal_spec.rb +4 -0
- data/spec/spec_helper.rb +1 -1
- data/web/build_site.rb +6 -2
- data/web/index.haml +2 -2
- metadata +61 -68
- metadata.gz.sig +0 -0
- data/examples/treemap/treemap.rb +0 -29
- data/examples/treemap/treemap_data.rb +0 -285
@@ -0,0 +1,267 @@
|
|
1
|
+
module Rubyvis
|
2
|
+
class Layout
|
3
|
+
# Alias for Rubyvis::Layout::Tree
|
4
|
+
def self.Tree
|
5
|
+
Rubyvis::Layout::Tree
|
6
|
+
end
|
7
|
+
# Implements a node-link tree diagram using the Reingold-Tilford "tidy"
|
8
|
+
# tree layout algorithm. The specific algorithm used by this layout is based on
|
9
|
+
# <a href="http://citeseer.ist.psu.edu/buchheim02improving.html">"Improving
|
10
|
+
# Walker's Algorithm to Run in Linear Time"</A> by C. Buchheim, M. Jünger
|
11
|
+
# & S. Leipert, Graph Drawing 2002. This layout supports both cartesian and
|
12
|
+
# radial orientations orientations for node-link diagrams.
|
13
|
+
#
|
14
|
+
# <p>The tree layout supports a "group" property, which if true causes siblings
|
15
|
+
# to be positioned closer together than unrelated nodes at the same depth. The
|
16
|
+
# layout can be configured using the <tt>depth</tt> and <tt>breadth</tt>
|
17
|
+
# properties, which control the increments in pixel space between nodes in both
|
18
|
+
# dimensions, similar to the indent layout.
|
19
|
+
#
|
20
|
+
# <p>For more details on how to use this layout, see
|
21
|
+
# {@link pv.Layout.Hierarchy}
|
22
|
+
class Tree < Hierarchy
|
23
|
+
@properties=Hierarchy.properties.dup
|
24
|
+
def initialize
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# :attr: breadth
|
30
|
+
# The offset between siblings nodes; defaults to 15.
|
31
|
+
|
32
|
+
##
|
33
|
+
# :attr: depth
|
34
|
+
# The offset between parent and child nodes; defaults to 60.
|
35
|
+
#
|
36
|
+
|
37
|
+
##
|
38
|
+
# :attr: orient
|
39
|
+
# The orientation. The default orientation is "top", which means that the root
|
40
|
+
# node is placed on the top edge, leaf nodes appear at the bottom, and internal
|
41
|
+
# nodes are in-between. The following orientations are supported:<ul>
|
42
|
+
#
|
43
|
+
# <li>left - left-to-right.
|
44
|
+
# <li>right - right-to-left.
|
45
|
+
# <li>top - top-to-bottom.
|
46
|
+
# <li>bottom - bottom-to-top.
|
47
|
+
# <li>radial - radially, with the root at the center.</ul>
|
48
|
+
#
|
49
|
+
|
50
|
+
##
|
51
|
+
# :group:
|
52
|
+
# The sibling grouping, i.e., whether differentiating space is placed between
|
53
|
+
# sibling groups. The default is 1 (or true), causing sibling leaves to be
|
54
|
+
# separated by one breadth offset. Setting this to false (or 0) causes
|
55
|
+
# non-siblings to be adjacent.
|
56
|
+
|
57
|
+
attr_accessor_dsl :group, :breadth, :depth, :orient
|
58
|
+
|
59
|
+
# Default properties for tree layouts. The default orientation is "top",
|
60
|
+
# the default group parameter is 1, and the default breadth and depth
|
61
|
+
# offsets are 15 and 60 respectively.
|
62
|
+
def self.defaults
|
63
|
+
Rubyvis::Layout::Tree.new.mark_extend(Rubyvis::Layout::Hierarchy.defaults).
|
64
|
+
group(1).
|
65
|
+
breadth(15).
|
66
|
+
depth(60).
|
67
|
+
orient("top")
|
68
|
+
end
|
69
|
+
|
70
|
+
def first_walk(v)
|
71
|
+
l,r,a=nil,nil,nil
|
72
|
+
if (!v.first_child)
|
73
|
+
l= v.previous_sibling
|
74
|
+
v.prelim = l.prelim + distance(v.depth, true) if l
|
75
|
+
else
|
76
|
+
l = v.first_child
|
77
|
+
r = v.last_child
|
78
|
+
a = l # default ancestor
|
79
|
+
v.each_child {|c|
|
80
|
+
first_walk(c)
|
81
|
+
a = apportion(c, a)
|
82
|
+
}
|
83
|
+
execute_shifts(v)
|
84
|
+
midpoint = 0.5 * (l.prelim + r.prelim)
|
85
|
+
l = v.previous_sibling
|
86
|
+
if l
|
87
|
+
v.prelim = l.prelim + distance(v.depth, true)
|
88
|
+
v.mod = v.prelim - midpoint
|
89
|
+
else
|
90
|
+
v.prelim = midpoint
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
def second_walk(v,m,depth)
|
95
|
+
v.breadth = v.prelim + m
|
96
|
+
m += v.mod
|
97
|
+
v.each_child {|c|
|
98
|
+
second_walk(c, m, depth)
|
99
|
+
}
|
100
|
+
end
|
101
|
+
def apportion(v,a)
|
102
|
+
w = v.previous_sibling
|
103
|
+
if w
|
104
|
+
vip = v
|
105
|
+
vop = v
|
106
|
+
vim = w
|
107
|
+
vom = v.parent_node.first_child
|
108
|
+
sip = vip.mod
|
109
|
+
sop = vop.mod
|
110
|
+
sim = vim.mod
|
111
|
+
som = vom.mod
|
112
|
+
nr = next_right(vim)
|
113
|
+
nl = next_left(vip)
|
114
|
+
while (nr and nl) do
|
115
|
+
vim = nr
|
116
|
+
vip = nl
|
117
|
+
vom = next_left(vom)
|
118
|
+
vop = next_right(vop)
|
119
|
+
vop.ancestor = v
|
120
|
+
shift = (vim.prelim + sim) - (vip.prelim + sip) + distance(vim.depth, false)
|
121
|
+
if (shift > 0)
|
122
|
+
move_subtree(ancestor(vim, v, a), v, shift)
|
123
|
+
sip += shift
|
124
|
+
sop += shift
|
125
|
+
end
|
126
|
+
sim += vim.mod
|
127
|
+
sip += vip.mod
|
128
|
+
som += vom.mod
|
129
|
+
sop += vop.mod
|
130
|
+
nr = next_right(vim)
|
131
|
+
nl = next_left(vip)
|
132
|
+
end
|
133
|
+
|
134
|
+
if (nr and !next_right(vop))
|
135
|
+
vop.thread = nr
|
136
|
+
vop.mod += sim - sop
|
137
|
+
end
|
138
|
+
if (nl and !next_left(vom))
|
139
|
+
vom.thread = nl
|
140
|
+
vom.mod += sip - som
|
141
|
+
a = v
|
142
|
+
end
|
143
|
+
end
|
144
|
+
a
|
145
|
+
end
|
146
|
+
|
147
|
+
def next_left(v)
|
148
|
+
v.first_child ? v.first_child : v.thread
|
149
|
+
end
|
150
|
+
def next_right(v)
|
151
|
+
v.last_child ? v.last_child : v.thread
|
152
|
+
end
|
153
|
+
|
154
|
+
def move_subtree(wm, wp, shift)
|
155
|
+
subtrees = wp.number - wm.number
|
156
|
+
wp.change -= shift / subtrees.to_f
|
157
|
+
wp.shift += shift
|
158
|
+
wm.change += shift / subtrees.to_f
|
159
|
+
wp.prelim += shift
|
160
|
+
wp.mod += shift
|
161
|
+
end
|
162
|
+
|
163
|
+
def execute_shifts(v)
|
164
|
+
shift = 0
|
165
|
+
change = 0
|
166
|
+
c=v.last_child
|
167
|
+
while c
|
168
|
+
c.prelim += shift
|
169
|
+
c.mod += shift
|
170
|
+
change += c.change
|
171
|
+
shift += c.shift + change
|
172
|
+
c = c.previous_sibling
|
173
|
+
end
|
174
|
+
end
|
175
|
+
def ancestor(vim, v, a)
|
176
|
+
(vim.ancestor.parent_node == v.parent_node) ? vim.ancestor : a
|
177
|
+
end
|
178
|
+
|
179
|
+
def distance(depth, siblings)
|
180
|
+
(siblings ? 1 : (@_group + 1)).to_f / ((@_orient == "radial") ? depth : 1)
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
def mid_angle(n)
|
185
|
+
(@_orient == "radial") ? n.breadth.to_f / depth : 0;
|
186
|
+
end
|
187
|
+
|
188
|
+
#/** @private */
|
189
|
+
def x(n)
|
190
|
+
case @_orient
|
191
|
+
when "left"
|
192
|
+
n.depth;
|
193
|
+
when "right"
|
194
|
+
@_w - n.depth;
|
195
|
+
when "top"
|
196
|
+
n.breadth + @_w / 2.0
|
197
|
+
when "bottom"
|
198
|
+
n.breadth + @_w / 2.0
|
199
|
+
when "radial"
|
200
|
+
@_w / 2.0 + n.depth * Math.cos(mid_angle(n))
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
#/** @private */
|
205
|
+
def y(n)
|
206
|
+
case @_orient
|
207
|
+
when "left"
|
208
|
+
n.breadth + @_h / 2.0
|
209
|
+
when "right"
|
210
|
+
n.breadth + @_h / 2.0
|
211
|
+
when "top"
|
212
|
+
n.depth;
|
213
|
+
when "bottom"
|
214
|
+
@_h - n.depth
|
215
|
+
when "radial"
|
216
|
+
@_h / 2.0 + n.depth * Math.sin(mid_angle(n))
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
def build_implied(s)
|
223
|
+
return nil if hierarchy_build_implied(s)
|
224
|
+
@_nodes = s.nodes
|
225
|
+
@_orient = s.orient
|
226
|
+
@_depth = s.depth
|
227
|
+
@_breadth = s.breadth
|
228
|
+
@_group = s.group
|
229
|
+
@_w = s.width
|
230
|
+
@_h = s.height
|
231
|
+
root=@_nodes[0]
|
232
|
+
root.visit_after {|v,i|
|
233
|
+
v.ancestor = v
|
234
|
+
v.prelim = 0
|
235
|
+
v.mod = 0
|
236
|
+
v.change = 0
|
237
|
+
v.shift = 0
|
238
|
+
v.number = v.previous_sibling ? (v.previous_sibling.number + 1) : 0
|
239
|
+
v.depth = i
|
240
|
+
}
|
241
|
+
#/* Compute the layout using Buchheim et al.'s algorithm. */
|
242
|
+
first_walk(root)
|
243
|
+
second_walk(root, -root.prelim, 0)
|
244
|
+
|
245
|
+
root.visit_after {|v,i|
|
246
|
+
v.breadth *= breadth
|
247
|
+
v.depth *= depth
|
248
|
+
v.mid_angle = mid_angle(v)
|
249
|
+
v.x = x(v)
|
250
|
+
v.y = y(v)
|
251
|
+
v.mid_angle += Math::PI if (v.first_child)
|
252
|
+
v.breadth=nil
|
253
|
+
v.depth=nil
|
254
|
+
v.ancestor=nil
|
255
|
+
v.prelim=nil
|
256
|
+
v.mod=nil
|
257
|
+
v.change=nil
|
258
|
+
v.shift=nil
|
259
|
+
v.number=nil
|
260
|
+
v.thread=nil
|
261
|
+
}
|
262
|
+
|
263
|
+
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
data/lib/rubyvis/mark.rb
CHANGED
@@ -699,7 +699,11 @@ module Rubyvis
|
|
699
699
|
width=self.parent ? self.parent.width() : (w+(l.nil? ? 0 : l)+(r.nil? ? 0 : r))
|
700
700
|
#puts (self.parent)? "parent width: #{self.parent.width}" : "no parent" if $DEBUG
|
701
701
|
#p prop.sort if $DEBUG
|
702
|
-
|
702
|
+
|
703
|
+
height=self.parent ? self.parent.height(): (h+(t.nil? ? 0 : t )+(b.nil? ? 0 : b))
|
704
|
+
|
705
|
+
puts "build implied #{type}: l:#{l},r:#{r},t:#{t},b:#{b}, w:#{prop[:width]} #{w},h: #{prop[:height]} #{h}, width:#{width}, height:#{height}" if $DEBUG
|
706
|
+
|
703
707
|
if w.nil?
|
704
708
|
r||=0
|
705
709
|
l||=0
|
@@ -715,7 +719,7 @@ module Rubyvis
|
|
715
719
|
l=width-w-r
|
716
720
|
end
|
717
721
|
|
718
|
-
|
722
|
+
|
719
723
|
|
720
724
|
if h.nil?
|
721
725
|
t||=0
|
@@ -739,11 +743,9 @@ module Rubyvis
|
|
739
743
|
s.top=t
|
740
744
|
s.bottom=b
|
741
745
|
|
742
|
-
puts "Post->left: #{l},right:#{r},top:#{t},bottom:#{b}, width:#{w}, height:#{h}" if $DEBUG
|
743
|
-
|
744
|
-
s.
|
745
|
-
#puts "width:#{s.width}" if $DEBUG
|
746
|
-
s.height=h if prop[:height]
|
746
|
+
puts "Post->left: #{l},right:#{r},top:#{t},bottom:#{b}, width:#{w}, height:#{h}\n\n" if $DEBUG
|
747
|
+
s.width = w if prop[:width]
|
748
|
+
s.height = h if prop[:height]
|
747
749
|
s.text_style=Rubyvis::Color.transparent if prop[:text_style] and !s.text_style
|
748
750
|
s.fill_style=Rubyvis::Color.transparent if prop[:fill_style] and !s.fill_style
|
749
751
|
s.stroke_style=Rubyvis::Color.transparent if prop[:stroke_style] and !s.stroke_style
|
@@ -874,7 +876,7 @@ module Rubyvis
|
|
874
876
|
@types[2].push(@seen[name])
|
875
877
|
end
|
876
878
|
}
|
877
|
-
end while(mark=mark.proto)
|
879
|
+
end while(mark = mark.proto)
|
878
880
|
@binds=OpenStruct.new({:properties=>@seen, :data=>@_data, :required=>@_required, :optional=>@types[1]+@types[2]+@types[3]
|
879
881
|
})
|
880
882
|
end
|
data/lib/rubyvis/mark/area.rb
CHANGED
@@ -55,9 +55,9 @@ module Rubyvis
|
|
55
55
|
# p binds.fixed
|
56
56
|
#/* Evaluate all properties on the first instance. */
|
57
57
|
else
|
58
|
-
binds.required = binds._required
|
59
|
-
binds.optional = binds._optional
|
60
|
-
binds.fixed = nil
|
58
|
+
binds.required = binds._required
|
59
|
+
binds.optional = binds._optional
|
60
|
+
binds.fixed = nil
|
61
61
|
end
|
62
62
|
# pp binds
|
63
63
|
mark_build_instance(s)
|
@@ -66,7 +66,7 @@ module Rubyvis
|
|
66
66
|
|
67
67
|
|
68
68
|
def area_bind
|
69
|
-
mark_bind
|
69
|
+
mark_bind
|
70
70
|
binds = self.binds
|
71
71
|
|
72
72
|
required = binds.required
|
@@ -80,8 +80,8 @@ module Rubyvis
|
|
80
80
|
}
|
81
81
|
optional.delete_if {|v| v.name=='segmented'}
|
82
82
|
# Cache the original arrays so they can be restored on build. */
|
83
|
-
@binds._required = required
|
84
|
-
@binds._optional = optional
|
83
|
+
@binds._required = required
|
84
|
+
@binds._optional = optional
|
85
85
|
end
|
86
86
|
|
87
87
|
|
data/lib/rubyvis/mark/dot.rb
CHANGED
@@ -21,7 +21,7 @@ module Rubyvis
|
|
21
21
|
# :attr: shape_size
|
22
22
|
# The size of the shape, in square pixels. Square pixels are used such that the
|
23
23
|
# area of the shape is linearly proportional to the value of the
|
24
|
-
# <tt>
|
24
|
+
# <tt>shape_size</tt> property, facilitating representative encodings. This is
|
25
25
|
# an alternative to using shape_radius
|
26
26
|
#
|
27
27
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class Rubyvis::Mark
|
2
2
|
##
|
3
|
-
# :section:
|
3
|
+
# :section: RBP Api
|
4
4
|
##
|
5
5
|
|
6
|
-
# Create
|
6
|
+
# Create a new Mark method shorcut.
|
7
7
|
def self.mark_method(name, mark) #:nodoc:
|
8
8
|
define_method(name) do |*args,&block|
|
9
9
|
opts=args[0]
|
@@ -240,5 +240,32 @@ class Rubyvis::Mark
|
|
240
240
|
# See Mark for examples of use
|
241
241
|
mark_method :layout_pack, Rubyvis::Layout::Pack
|
242
242
|
|
243
|
+
##
|
244
|
+
# :method: layout_grid(opts,&block)
|
245
|
+
#
|
246
|
+
# Adds a Layout::Grid to current mark.
|
247
|
+
#
|
248
|
+
# If a block is provided, the context will be defined differently if
|
249
|
+
# parameter is provided
|
250
|
+
# * Without parameter: block executed inside context of new mark
|
251
|
+
# * With paramenter: block executed inside context of current mark.
|
252
|
+
# Paramenter references new mark
|
253
|
+
#
|
254
|
+
# See Mark for examples of use
|
255
|
+
mark_method :layout_grid, Rubyvis::Layout::Grid
|
256
|
+
|
257
|
+
##
|
258
|
+
# :method: tree_grid(opts,&block)
|
259
|
+
#
|
260
|
+
# Adds a Layout::Tree to current mark.
|
261
|
+
#
|
262
|
+
# If a block is provided, the context will be defined differently if
|
263
|
+
# parameter is provided
|
264
|
+
# * Without parameter: block executed inside context of new mark
|
265
|
+
# * With paramenter: block executed inside context of current mark.
|
266
|
+
# Paramenter references new mark
|
267
|
+
#
|
268
|
+
# See Mark for examples of use
|
269
|
+
mark_method :layout_tree, Rubyvis::Layout::Tree
|
243
270
|
|
244
271
|
end
|
data/lib/rubyvis/nest.rb
CHANGED
@@ -90,6 +90,22 @@ module Rubyvis
|
|
90
90
|
@order = order.nil? ? Rubyvis.natural_order : order
|
91
91
|
return self
|
92
92
|
end
|
93
|
+
|
94
|
+
# Returns a hierarchical map of values. Each key adds one level to the
|
95
|
+
# hierarchy. With only a single key, the returned map will have a key for each
|
96
|
+
# distinct value of the key function; the correspond value with be an array of
|
97
|
+
# elements with that key value. If a second key is added, this will be a nested
|
98
|
+
# map. For example:
|
99
|
+
#
|
100
|
+
# <pre>Rubyvis.nest(yields)
|
101
|
+
# .key(function(d) d.variety)
|
102
|
+
# .key(function(d) d.site)
|
103
|
+
# .map()</pre>
|
104
|
+
#
|
105
|
+
# returns a map <tt>m</tt> such that <tt>m[variety][site]</tt> is an array, a subset of
|
106
|
+
# <tt>yields</tt>, with each element having the given variety and site.
|
107
|
+
#
|
108
|
+
# @returns a hierarchical map of values
|
93
109
|
def map
|
94
110
|
#i=0
|
95
111
|
map={}
|
@@ -116,6 +132,19 @@ module Rubyvis
|
|
116
132
|
end
|
117
133
|
map
|
118
134
|
end
|
135
|
+
|
136
|
+
# Returns a hierarchical nested array. This method is similar to
|
137
|
+
# {@link pv.entries}, but works recursively on the entire hierarchy. Rather
|
138
|
+
# than returning a map like {@link #map}, this method returns a nested
|
139
|
+
# array. Each element of the array has a <tt>key</tt> and <tt>values</tt>
|
140
|
+
# field. For leaf nodes, the <tt>values</tt> array will be a subset of the
|
141
|
+
# underlying elements array; for non-leaf nodes, the <tt>values</tt> array will
|
142
|
+
# contain more key-values pairs.
|
143
|
+
#
|
144
|
+
# <p>For an example usage, see the {@link Nest} constructor.
|
145
|
+
#
|
146
|
+
# @returns a hierarchical nested array.
|
147
|
+
|
119
148
|
def entries()
|
120
149
|
entries_sort(entries_entries(map),0)
|
121
150
|
end
|
@@ -145,13 +174,30 @@ module Rubyvis
|
|
145
174
|
if value.is_a? Array
|
146
175
|
map[key]=f.call(value)
|
147
176
|
else
|
148
|
-
rollup_rollup(value)
|
177
|
+
rollup_rollup(value,f)
|
149
178
|
end
|
150
179
|
}
|
151
180
|
return map;
|
152
181
|
end
|
182
|
+
|
183
|
+
# Returns a rollup map. The behavior of this method is the same as
|
184
|
+
# {@link #map}, except that the leaf values are replaced with the return value
|
185
|
+
# of the specified rollup function <tt>f</tt>. For example,
|
186
|
+
#
|
187
|
+
# <pre>pv.nest(yields)
|
188
|
+
# .key(function(d) d.site)
|
189
|
+
# .rollup(function(v) pv.median(v, function(d) d.yield))</pre>
|
190
|
+
#
|
191
|
+
# first groups yield data by site, and then returns a map from site to median
|
192
|
+
# yield for the given site.
|
193
|
+
#
|
194
|
+
# @see #map
|
195
|
+
# @param {function} f a rollup function.
|
196
|
+
# @returns a hierarchical map, with the leaf values computed by <tt>f</tt>.
|
197
|
+
|
198
|
+
|
153
199
|
def rollup(f)
|
154
|
-
rollup_rollup(self.map,f)
|
200
|
+
rollup_rollup(self.map, f)
|
155
201
|
end
|
156
202
|
end
|
157
203
|
end
|