plotrb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +38 -0
- data/README.rdoc +77 -0
- data/Rakefile +7 -0
- data/examples/arc.rb +31 -0
- data/examples/area.rb +48 -0
- data/examples/bar.rb +44 -0
- data/examples/barley.rb +66 -0
- data/examples/choropleth.rb +48 -0
- data/examples/lifelines.rb +106 -0
- data/examples/scatter.rb +43 -0
- data/lib/plotrb.rb +25 -0
- data/lib/plotrb/axes.rb +208 -0
- data/lib/plotrb/base.rb +193 -0
- data/lib/plotrb/data.rb +232 -0
- data/lib/plotrb/kernel.rb +136 -0
- data/lib/plotrb/legends.rb +168 -0
- data/lib/plotrb/marks.rb +459 -0
- data/lib/plotrb/scales.rb +346 -0
- data/lib/plotrb/simple.rb +197 -0
- data/lib/plotrb/transforms.rb +592 -0
- data/lib/plotrb/version.rb +3 -0
- data/lib/plotrb/visualization.rb +55 -0
- data/plotrb.gemspec +27 -0
- data/spec/plotrb/axes_spec.rb +227 -0
- data/spec/plotrb/base_spec.rb +321 -0
- data/spec/plotrb/data_spec.rb +258 -0
- data/spec/plotrb/kernel_spec.rb +54 -0
- data/spec/plotrb/legends_spec.rb +157 -0
- data/spec/plotrb/marks_spec.rb +46 -0
- data/spec/plotrb/scales_spec.rb +187 -0
- data/spec/plotrb/simple_spec.rb +61 -0
- data/spec/plotrb/transforms_spec.rb +248 -0
- data/spec/plotrb/visualization_spec.rb +93 -0
- data/spec/plotrb_spec.rb +5 -0
- data/spec/spec_helper.rb +12 -0
- metadata +180 -0
@@ -0,0 +1,592 @@
|
|
1
|
+
module Plotrb
|
2
|
+
|
3
|
+
# Data transform performs operations on a data set prior to
|
4
|
+
# visualization.
|
5
|
+
# See {https://github.com/trifacta/vega/wiki/Data-Transforms}
|
6
|
+
class Transform
|
7
|
+
|
8
|
+
include ::Plotrb::Base
|
9
|
+
|
10
|
+
# all available types of transforms defined by Vega
|
11
|
+
TYPES = %i(array copy cross facet filter flatten fold formula slice sort
|
12
|
+
stats truncate unique window zip force geo geopath link pie stack
|
13
|
+
treemap wordcloud)
|
14
|
+
|
15
|
+
TYPES.each do |t|
|
16
|
+
define_singleton_method(t) do |&block|
|
17
|
+
::Plotrb::Transform.new(t, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @!attributes type
|
22
|
+
# @return [Symbol] the transform type
|
23
|
+
add_attributes :type
|
24
|
+
|
25
|
+
def initialize(type, &block)
|
26
|
+
@type = type
|
27
|
+
@extra_fields = [:index, :data]
|
28
|
+
self.send(@type)
|
29
|
+
self.instance_eval(&block) if block_given?
|
30
|
+
::Plotrb::Kernel.transforms << self
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def type
|
35
|
+
@type
|
36
|
+
end
|
37
|
+
|
38
|
+
def extra_fields
|
39
|
+
@extra_fields
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Data Manipulation Transforms
|
45
|
+
|
46
|
+
def array
|
47
|
+
# @!attributes fields
|
48
|
+
# @return [Array<String>] array of field references to copy
|
49
|
+
add_attributes(:fields)
|
50
|
+
define_multi_val_attribute(:fields)
|
51
|
+
self.singleton_class.class_eval { alias_method :take, :fields }
|
52
|
+
end
|
53
|
+
|
54
|
+
def copy
|
55
|
+
# @!attributes from
|
56
|
+
# @return [String] the name of the object to copy values from
|
57
|
+
# @!attributes fields
|
58
|
+
# @return [Array<String>] the fields to copy
|
59
|
+
# @!attributes as
|
60
|
+
# @return [Array<String>] the field names to copy the values to
|
61
|
+
add_attributes(:from, :fields, :as)
|
62
|
+
define_single_val_attribute(:from)
|
63
|
+
define_multi_val_attributes(:fields, :as)
|
64
|
+
self.singleton_class.class_eval { alias_method :take, :fields }
|
65
|
+
end
|
66
|
+
|
67
|
+
def cross
|
68
|
+
# @!attributes with
|
69
|
+
# @return [String] the name of the secondary data to cross with
|
70
|
+
# @!attributes diagonal
|
71
|
+
# @return [Boolean] whether diagonal of cross-product will be included
|
72
|
+
add_attributes(:with, :diagonal)
|
73
|
+
define_single_val_attribute(:with)
|
74
|
+
define_boolean_attribute(:diagonal)
|
75
|
+
self.singleton_class.class_eval {
|
76
|
+
alias_method :include_diagonal, :diagonal
|
77
|
+
alias_method :include_diagonal?, :diagonal?
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def facet
|
82
|
+
# @!attributes keys
|
83
|
+
# @return [Array<String>] the fields to use as keys
|
84
|
+
# @!attributes sort
|
85
|
+
# @return [String, Array<String>] sort criteria
|
86
|
+
add_attributes(:keys, :sort)
|
87
|
+
define_multi_val_attributes(:keys, :sort)
|
88
|
+
self.singleton_class.class_eval { alias_method :group_by, :keys }
|
89
|
+
@extra_fields.concat([:key])
|
90
|
+
end
|
91
|
+
|
92
|
+
def filter
|
93
|
+
# @!attributes test
|
94
|
+
# @return [String] the expression for the filter predicate, which
|
95
|
+
# includes the variable `d`, corresponding to the current data object
|
96
|
+
add_attributes(:test)
|
97
|
+
define_single_val_attribute(:test)
|
98
|
+
end
|
99
|
+
|
100
|
+
def flatten
|
101
|
+
# no parameter needed
|
102
|
+
end
|
103
|
+
|
104
|
+
def fold
|
105
|
+
# @!attributes fields
|
106
|
+
# @return [Array<String>] the field references indicating the data
|
107
|
+
# properties to fold
|
108
|
+
add_attributes(:fields)
|
109
|
+
define_multi_val_attribute(:fields)
|
110
|
+
self.singleton_class.class_eval { alias_method :into, :fields }
|
111
|
+
@extra_fields.concat([:key, :value])
|
112
|
+
end
|
113
|
+
|
114
|
+
def formula
|
115
|
+
# @!attributes field
|
116
|
+
# @return [String] the property name in which to store the value
|
117
|
+
# @!attributes
|
118
|
+
# @return expr [String] the expression for the formula
|
119
|
+
add_attributes(:field, :expr)
|
120
|
+
define_single_val_attributes(:field, :expr)
|
121
|
+
self.singleton_class.class_eval {
|
122
|
+
alias_method :into, :field
|
123
|
+
alias_method :apply, :expr
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
def slice
|
128
|
+
# @!attributes by
|
129
|
+
# @return [Integer, Array<Integer>, Symbol] the sub-array to copy
|
130
|
+
# @!attributes field
|
131
|
+
# @return [String] the data field to copy the max, min or median value
|
132
|
+
add_attributes(:by, :field)
|
133
|
+
define_single_val_attributes(:by, :field)
|
134
|
+
end
|
135
|
+
|
136
|
+
# TODO: allow reverse sort
|
137
|
+
def sort
|
138
|
+
# @!attributes by
|
139
|
+
# @return [String, Array<String>] a list of fields to use as sort
|
140
|
+
# criteria
|
141
|
+
add_attributes(:by)
|
142
|
+
define_multi_val_attribute(:by)
|
143
|
+
end
|
144
|
+
|
145
|
+
def stats
|
146
|
+
# @!attributes value
|
147
|
+
# @return [String] the field for which to computer the statistics
|
148
|
+
# @!attributes median
|
149
|
+
# @return [Boolean] whether median will be computed
|
150
|
+
# @!attributes assign
|
151
|
+
# @return [Boolean] whether add stat property to each data element
|
152
|
+
add_attributes(:value, :median, :assign)
|
153
|
+
define_single_val_attribute(:value)
|
154
|
+
define_boolean_attributes(:median, :assign)
|
155
|
+
self.singleton_class.class_eval {
|
156
|
+
alias_method :from, :value
|
157
|
+
alias_method :include_median, :median
|
158
|
+
alias_method :include_median?, :median?
|
159
|
+
alias_method :store_stats, :assign
|
160
|
+
alias_method :store_stats?, :assign?
|
161
|
+
}
|
162
|
+
@extra_fields.concat([:count, :min, :max, :sum, :mean, :variance, :stdev,
|
163
|
+
:median])
|
164
|
+
end
|
165
|
+
|
166
|
+
def truncate
|
167
|
+
# @!attributes value
|
168
|
+
# @return [String] the field containing values to truncate
|
169
|
+
# @!attributes output
|
170
|
+
# @return [String] the field to store the truncated values
|
171
|
+
# @!attributes limit
|
172
|
+
# @return [Integer] maximum length of truncated string
|
173
|
+
# @!attributes position
|
174
|
+
# @return [Symbol] the position from which to remove text
|
175
|
+
# @!attributes ellipsis
|
176
|
+
# @return [String] the ellipsis for truncated text
|
177
|
+
# @!attributes wordbreak
|
178
|
+
# @return [Boolean] whether to truncate along word boundaries
|
179
|
+
add_attributes(:value, :output, :limit, :position, :ellipsis, :wordbreak)
|
180
|
+
define_single_val_attributes(:value, :output, :limit, :position,
|
181
|
+
:ellipsis)
|
182
|
+
define_boolean_attribute(:wordbreak)
|
183
|
+
self.singleton_class.class_eval {
|
184
|
+
alias_method :from, :value
|
185
|
+
alias_method :to, :output
|
186
|
+
alias_method :max_length, :limit
|
187
|
+
}
|
188
|
+
define_singleton_method :method_missing do |method, *args, &block|
|
189
|
+
if method.to_s =~ /^in_(front|back|middle)$/
|
190
|
+
self.position($1.to_sym, &block)
|
191
|
+
else
|
192
|
+
super
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def unique
|
198
|
+
# @!attributes field
|
199
|
+
# @return [String] the data field for which to compute unique value
|
200
|
+
# @!attributes as
|
201
|
+
# @return [String] the field name to store the unique values
|
202
|
+
add_attributes(:field, :as)
|
203
|
+
define_single_val_attributes(:field, :as)
|
204
|
+
self.singleton_class.class_eval {
|
205
|
+
alias_method :from, :field
|
206
|
+
alias_method :to, :as
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
210
|
+
def window
|
211
|
+
# @!attributes size
|
212
|
+
# @return [Integer] the size of the sliding window
|
213
|
+
# @!attributes step
|
214
|
+
# @return [Integer] the step size to advance the window per frame
|
215
|
+
add_attributes(:size, :step)
|
216
|
+
define_single_val_attributes(:size, :step)
|
217
|
+
end
|
218
|
+
|
219
|
+
def zip
|
220
|
+
# @!attributes with
|
221
|
+
# @return [String] the name of the secondary data set to zip with the
|
222
|
+
# primary data set
|
223
|
+
# @!attributes as
|
224
|
+
# @return [String] the name of the field to store the secondary data set
|
225
|
+
# values
|
226
|
+
# @!attributes key
|
227
|
+
# @return [String] the field in the primary data set to match against
|
228
|
+
# the secondary data set
|
229
|
+
# @!attributes with_key
|
230
|
+
# @return [String] the field in the secondary data set to match
|
231
|
+
# against the primary data set
|
232
|
+
# @!attributes default
|
233
|
+
# @return [] a default value to use if no matching key value is found
|
234
|
+
add_attributes(:with, :as, :key, :with_key, :default)
|
235
|
+
define_single_val_attributes(:with, :as, :default, :key, :with_key)
|
236
|
+
self.singleton_class.class_eval {
|
237
|
+
alias_method :match, :key
|
238
|
+
alias_method :against, :with_key
|
239
|
+
}
|
240
|
+
end
|
241
|
+
|
242
|
+
# Visual Encoding Transforms
|
243
|
+
|
244
|
+
def force
|
245
|
+
# @!attributes links
|
246
|
+
# @return [String] the name of the link (edge) data set, must have
|
247
|
+
# `source` and `target` attributes
|
248
|
+
# @!attributes size
|
249
|
+
# @return [Array(Integer, Integer)] the dimensions of the layout
|
250
|
+
# @!attributes iterations
|
251
|
+
# @return [Integer] the number of iterations to run
|
252
|
+
# @!attributes charge
|
253
|
+
# @return [Numeric, String] the strength of the charge each node exerts
|
254
|
+
# @!attributes link_distance
|
255
|
+
# @return [Integer, String] the length of edges
|
256
|
+
# @!attributes link_strength
|
257
|
+
# @return [Numeric, String] the tension of edges
|
258
|
+
# @!attributes friction
|
259
|
+
# @return [Numeric] the strength of the friction force used to
|
260
|
+
# stabilize the layout
|
261
|
+
# @!attributes theta
|
262
|
+
# @return [Numeric] the theta parameter for the Barnes-Hut algorithm
|
263
|
+
# used to compute charge forces between nodes
|
264
|
+
# @!attributes gravity
|
265
|
+
# @return [Numeric] the strength of the pseudo-gravity force that pulls
|
266
|
+
# nodes towards the center of the layout area
|
267
|
+
# @!attributes alpha
|
268
|
+
# @return [Numeric] a "temperature" parameter that determines how much
|
269
|
+
# node positions are adjusted at each step
|
270
|
+
attr = [:links, :size, :iterations, :charge, :link_distance,
|
271
|
+
:link_strength, :friction, :theta, :gravity, :alpha]
|
272
|
+
add_attributes(*attr)
|
273
|
+
define_single_val_attributes(*attr)
|
274
|
+
end
|
275
|
+
|
276
|
+
def geo
|
277
|
+
# @!attributes projection
|
278
|
+
# @return [String] the type of cartographic projection to use
|
279
|
+
# @!attributes lon
|
280
|
+
# @return [String] the input longitude values
|
281
|
+
# @!attributes lat
|
282
|
+
# @return [String] the input latitude values
|
283
|
+
# @!attributes center
|
284
|
+
# @return [Array(Integer, Integer)] the center of the projection
|
285
|
+
# @!attributes translate
|
286
|
+
# @return [Array(Integer, Integer)] the translation of the projection
|
287
|
+
# @!attributes scale
|
288
|
+
# @return [Numeric] the scale of the projection
|
289
|
+
# @!attributes rotate
|
290
|
+
# @return [Numeric] the rotation of the projection
|
291
|
+
# @!attributes precision
|
292
|
+
# @return [Numeric] the desired precision of the projection
|
293
|
+
# @!attributes clip_angle
|
294
|
+
# @return [Numeric] the clip angle of the projection
|
295
|
+
attr = [:projection, :lon, :lat, :center, :translate, :scale,
|
296
|
+
:rotate, :precision, :clip_angle]
|
297
|
+
add_attributes(*attr)
|
298
|
+
define_single_val_attributes(*attr)
|
299
|
+
end
|
300
|
+
|
301
|
+
def geopath
|
302
|
+
# @!attributes value
|
303
|
+
# @return [String] the data field containing the GeoJSON feature data
|
304
|
+
# @!attributes (see #geo)
|
305
|
+
attr = [:value, :projection, :center, :translate, :scale, :rotate,
|
306
|
+
:precision, :clip_angle]
|
307
|
+
add_attributes(*attr)
|
308
|
+
define_single_val_attributes(*attr)
|
309
|
+
@value ||= 'data'
|
310
|
+
@extra_fields.concat([:path])
|
311
|
+
end
|
312
|
+
|
313
|
+
def link
|
314
|
+
# @!attributes source
|
315
|
+
# @return [String] the data field that references the source node for
|
316
|
+
# this link
|
317
|
+
# @!attributes target
|
318
|
+
# @return [String] the data field that references the target node for
|
319
|
+
# this link
|
320
|
+
# @!attributes shape
|
321
|
+
# @return [Symbol] the path shape to use
|
322
|
+
# @!attributes tension
|
323
|
+
# @return [Numeric] the tension in the range [0,1] for the "tightness"
|
324
|
+
# of 'curve'-shaped links
|
325
|
+
attr = [:source, :target, :shape, :tension]
|
326
|
+
add_attributes(*attr)
|
327
|
+
define_single_val_attributes(*attr)
|
328
|
+
@extra_fields.concat([:path])
|
329
|
+
end
|
330
|
+
|
331
|
+
def pie
|
332
|
+
# @!attributes sort
|
333
|
+
# @return [Boolean] whether to sort the data prior to computing angles
|
334
|
+
# @!attributes value
|
335
|
+
# @return [String] the data values to encode as angular spans
|
336
|
+
add_attributes(:sort, :value)
|
337
|
+
define_boolean_attribute(:sort)
|
338
|
+
define_single_val_attribute(:value)
|
339
|
+
@extra_fields.concat([:start_angle, :end_angle])
|
340
|
+
end
|
341
|
+
|
342
|
+
def stack
|
343
|
+
# @!attributes point
|
344
|
+
# @return [String] the data field determining the points at which to
|
345
|
+
# stack
|
346
|
+
# @!attributes height
|
347
|
+
# @return [String] the data field determining the height of a stack
|
348
|
+
# @!attributes offset
|
349
|
+
# @return [Symbol] the baseline offset style
|
350
|
+
# @!attributes order
|
351
|
+
# @return [Symbol] the sort order for stack layers
|
352
|
+
attr = [:point, :height, :offset, :order]
|
353
|
+
add_attributes(*attr)
|
354
|
+
define_single_val_attributes(*attr)
|
355
|
+
@extra_fields.concat([:y, :y2])
|
356
|
+
end
|
357
|
+
|
358
|
+
def treemap
|
359
|
+
# @!attributes padding
|
360
|
+
# @return [Integer, Array(Integer, Integer, Integer, Integer)] the
|
361
|
+
# padding to provide around the internal nodes in the treemap
|
362
|
+
# @!attributes ratio
|
363
|
+
# @return [Numeric] the target aspect ratio for the layout to optimize
|
364
|
+
# @!attributes round
|
365
|
+
# @return [Boolean] whether cell dimensions will be rounded to integer
|
366
|
+
# pixels
|
367
|
+
# @!attributes size
|
368
|
+
# @return [Array(Integer, Integer)] the dimensions of the layout
|
369
|
+
# @!attributes sticky
|
370
|
+
# @return [Boolean] whether repeated runs of the treemap will use cached
|
371
|
+
# partition boundaries
|
372
|
+
# @!attributes value
|
373
|
+
# @return [String] the values to use to determine the area of each
|
374
|
+
# leaf-level treemap cell
|
375
|
+
add_attributes(:padding, :ratio, :round, :size, :sticky, :value)
|
376
|
+
define_single_val_attributes(:padding, :ratio, :size, :value)
|
377
|
+
define_boolean_attributes(:round, :sticky)
|
378
|
+
@extra_fields.concat([:x, :y, :width, :height])
|
379
|
+
end
|
380
|
+
|
381
|
+
def wordcloud
|
382
|
+
# @!attributes font
|
383
|
+
# @return [String] the font face to use within the word cloud
|
384
|
+
# @!attributes font_size
|
385
|
+
# @return [String] the font size for a word
|
386
|
+
# @!attributes font_style
|
387
|
+
# @return [String] the font style to use
|
388
|
+
# @!attributes font_weight
|
389
|
+
# @return [String] the font weight to use
|
390
|
+
# @!attributes padding
|
391
|
+
# @return [Integer, Array(Integer, Integer, Integer, Integer)] the
|
392
|
+
# padding to provide around text in the word cloud
|
393
|
+
# @!attributes rotate
|
394
|
+
# @return [String, Hash] the rotation angle for a word
|
395
|
+
# @!attributes size
|
396
|
+
# @return [Array(Integer, Integer)] the dimensions of the layout
|
397
|
+
# @!attributes text
|
398
|
+
# @return [String] the data field containing the text to visualize
|
399
|
+
attr = [:font, :font_size, :font_style, :font_weight, :padding,
|
400
|
+
:rotate, :size, :text]
|
401
|
+
add_attributes(*attr)
|
402
|
+
define_single_val_attribute(*attr)
|
403
|
+
@extra_fields.concat([:x, :y, :font_size, :font, :angle])
|
404
|
+
end
|
405
|
+
|
406
|
+
def attribute_post_processing
|
407
|
+
process_array_fields
|
408
|
+
process_copy_as
|
409
|
+
process_facet_keys
|
410
|
+
process_filter_test
|
411
|
+
process_fold_fields
|
412
|
+
process_slice_field
|
413
|
+
process_stats_value
|
414
|
+
process_unique_field
|
415
|
+
process_truncate_value
|
416
|
+
process_zip_key
|
417
|
+
process_zip_with_key
|
418
|
+
process_zip_as
|
419
|
+
process_geo_lon
|
420
|
+
process_geo_lat
|
421
|
+
process_link_source
|
422
|
+
process_link_target
|
423
|
+
process_pie_value
|
424
|
+
process_stack_order
|
425
|
+
process_stack_point
|
426
|
+
process_stack_height
|
427
|
+
process_treemap_value
|
428
|
+
process_wordcloud_text
|
429
|
+
process_wordcloud_font_size
|
430
|
+
end
|
431
|
+
|
432
|
+
def process_array_fields
|
433
|
+
return unless @type == :array && @fields
|
434
|
+
@fields.collect! { |f| get_full_field_ref(f) }
|
435
|
+
end
|
436
|
+
|
437
|
+
def process_copy_as
|
438
|
+
return unless @type == :copy && @as && @fields
|
439
|
+
if @as.is_a?(Array) && @as.size != @fields.size
|
440
|
+
raise ArgumentError, 'Unmatched number of fields for copy transform'
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
def process_cross_with
|
445
|
+
return unless @type == :cross && @with
|
446
|
+
case @with
|
447
|
+
when String
|
448
|
+
unless ::Plotrb::Kernel.find_data(@with)
|
449
|
+
raise ArgumentError, 'Invalid data for cross transform'
|
450
|
+
end
|
451
|
+
when ::Plotrb::Data
|
452
|
+
@with = @with.name
|
453
|
+
else
|
454
|
+
raise ArgumentError, 'Invalid data for cross transform'
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
def process_facet_keys
|
459
|
+
return unless @type == :facet && @keys
|
460
|
+
@keys.collect! { |k| get_full_field_ref(k) }
|
461
|
+
end
|
462
|
+
|
463
|
+
def process_filter_test
|
464
|
+
return unless @type == :filter && @test
|
465
|
+
unless @test =~ /d\./
|
466
|
+
raise ArgumentError, 'Invalid filter test string, prefix with \'d.\''
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
def process_fold_fields
|
471
|
+
return unless @type == :fold && @fields
|
472
|
+
@fields.collect! { |f| get_full_field_ref(f) }
|
473
|
+
end
|
474
|
+
|
475
|
+
def process_slice_field
|
476
|
+
return unless @type == :slice && @field
|
477
|
+
@field = get_full_field_ref(@field)
|
478
|
+
end
|
479
|
+
|
480
|
+
def process_stats_value
|
481
|
+
return unless @type == :stats && @value
|
482
|
+
@value = get_full_field_ref(@value)
|
483
|
+
end
|
484
|
+
|
485
|
+
def process_unique_field
|
486
|
+
return unless @type == :unique && @field
|
487
|
+
@field = get_full_field_ref(@field)
|
488
|
+
end
|
489
|
+
|
490
|
+
def process_truncate_value
|
491
|
+
return unless @type == :truncate && @value
|
492
|
+
@value = get_full_field_ref(@value)
|
493
|
+
end
|
494
|
+
|
495
|
+
def process_zip_key
|
496
|
+
return unless @type == :zip && @key
|
497
|
+
@key = get_full_field_ref(@key)
|
498
|
+
end
|
499
|
+
|
500
|
+
def process_zip_with_key
|
501
|
+
return unless @type == :zip && @with_key
|
502
|
+
@with_key = get_full_field_ref(@with_key)
|
503
|
+
end
|
504
|
+
|
505
|
+
def process_zip_as
|
506
|
+
return unless @type == :zip && @as
|
507
|
+
@extra_fields.concat([@as.to_sym])
|
508
|
+
end
|
509
|
+
|
510
|
+
def process_geo_lon
|
511
|
+
return unless @type == :geo && @lon
|
512
|
+
@lon = get_full_field_ref(@lon)
|
513
|
+
end
|
514
|
+
|
515
|
+
def process_geo_lat
|
516
|
+
return unless @type == :geo && @lat
|
517
|
+
@lat = get_full_field_ref(@lat)
|
518
|
+
end
|
519
|
+
|
520
|
+
def process_link_source
|
521
|
+
return unless @type == :link && @source
|
522
|
+
@source = get_full_field_ref(@source)
|
523
|
+
end
|
524
|
+
|
525
|
+
def process_link_target
|
526
|
+
return unless @type == :link && @target
|
527
|
+
@target = get_full_field_ref(@target)
|
528
|
+
end
|
529
|
+
|
530
|
+
def process_pie_value
|
531
|
+
return unless @type == :pie
|
532
|
+
if @value
|
533
|
+
@value = get_full_field_ref(@value)
|
534
|
+
else
|
535
|
+
@value = 'data'
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
def process_stack_order
|
540
|
+
return unless @order
|
541
|
+
case @order
|
542
|
+
when :default, 'default', :reverse, 'reverse'
|
543
|
+
when :inside_out, 'inside-out', 'inside_out'
|
544
|
+
@order = 'inside-out'
|
545
|
+
else
|
546
|
+
raise ArgumentError, 'Unsupported stack order'
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
550
|
+
def process_stack_point
|
551
|
+
return unless @type == :stack && @point
|
552
|
+
@point = get_full_field_ref(@point)
|
553
|
+
end
|
554
|
+
|
555
|
+
def process_stack_height
|
556
|
+
return unless @type == :stack && @height
|
557
|
+
@height = get_full_field_ref(@height)
|
558
|
+
end
|
559
|
+
|
560
|
+
def process_treemap_value
|
561
|
+
return unless @type == :treemap && @value
|
562
|
+
@value = get_full_field_ref(@value)
|
563
|
+
end
|
564
|
+
|
565
|
+
def process_wordcloud_text
|
566
|
+
return unless @type == :wordcloud && @text
|
567
|
+
@text = get_full_field_ref(@text)
|
568
|
+
end
|
569
|
+
|
570
|
+
def process_wordcloud_font_size
|
571
|
+
return unless @type == :wordcloud && @font_size
|
572
|
+
@font_size = get_full_field_ref(@font_size)
|
573
|
+
end
|
574
|
+
|
575
|
+
def get_full_field_ref(field)
|
576
|
+
case field
|
577
|
+
when String
|
578
|
+
if field.start_with?('data.') || extra_fields.include?(field.to_sym)
|
579
|
+
field
|
580
|
+
else
|
581
|
+
"data.#{field}"
|
582
|
+
end
|
583
|
+
when ::Plotrb::Data
|
584
|
+
'data'
|
585
|
+
else
|
586
|
+
raise ArgumentError, 'Invalid data field'
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
end
|
591
|
+
|
592
|
+
end
|