22
33module UnicodePlot
44
5- # == Description
5+ # ## Description
66 #
77 # Draw a stem-leaf plot of the given vector +vec+.
8- #
9- # stemplot(vec, **kwargs)
10- #
8+ #
9+ # ```
10+ # stemplot(vec, **kwargs)
11+ # ```
1112 #
1213 # Draw a back-to-back stem-leaf plot of the given vectors +vec1+ and +vec2+.
13- #
14- # stemplot(vec, vec2, **kwargs)
15- #
14+ #
15+ # ```
16+ # stemplot(vec1, vec2, **kwargs)
17+ # ```
18+ #
1619 # The vectors can be any object that converts to an Array, e.g. an Array, Range, etc.
1720 # If all elements of the vector are Numeric, the stem-leaf plot is classified as a
18- # + NumericStemplot+ , otherwise it is classified as a StringStemplot. Back-to-back
21+ # { NumericStemplot} , otherwise it is classified as a { StringStemplot} . Back-to-back
1922 # stem-leaf plots must be the same type, i.e. String and Numeric stem-leaf plots cannot
2023 # be mixed in a back-to-back plot.
2124 #
22- # == Usage
25+ # ## Usage
2326 #
24- # stemplot(vec, [vec2], scale:, divider:, padchar:, trim: )
27+ # stemplot(vec, [vec2], scale:, divider:, padchar:, trim: )
2528 #
26- # == Arguments
29+ # ## Arguments
2730 #
2831 # - +vec+: Vector for which the stem leaf plot should be computed.
2932 # - +vec2+: Optional secondary vector, will be used to create a back-to-back stem-leaf plot.
@@ -33,56 +36,61 @@ module UnicodePlot
3336 # - +trim+: Trims the stem labels when there are no leaves. This can be useful if your data is sparse. Default = +false+
3437 # - +string_padchar+: Character used to replace missing position for input strings shorter than the stem-size. Default = "_"
3538 #
36- # == Results
37- # A plot of object type is sent to $stdout
38- #
39- # == Examples using Numbers
40- #
41- # # Generate some numbers
42- # fifty_floats = 50.times.map { rand(-1000..1000)/350.0 }
43- # eighty_ints = 80.times.map { rand(1..100) }
44- # another_eighty_ints = 80.times.map { rand(1..100) }
45- # three_hundred_ints = 300.times.map { rand(-100..100) }
46- #
47- # # Single sided stem-plot
48- # UnicodePlot.stemplot(eighty_ints)
49- #
50- # # Single sided stem-plot with positive and negative values
51- # UnicodePlot.stemplot(three_hundred_ints)
52- #
53- # # Single sided stem-plot using floating point values, scaled
54- # UnicodePlot.stemplot(fifty_floats, scale: 1)
55- #
56- # # Single sided stem-plot using floating point values, scaled with new divider
57- # UnicodePlot.stemplot(fifty_floats, scale: 1, divider: "😄")
58- #
59- # # Back to back stem-plot
60- # UnicodePlot.stemplot(eighty_ints, another_eighty_ints)
61- #
62- # == Examples using Strings
63- #
64- # # Generate some strings
65- # words_1 = %w[apple junk ant age bee bar baz dog egg a]
66- # words_2 = %w[ape flan can cat juice elf gnome child fruit]
39+ # ## Result
40+ # A plot of object type is sent to <tt>$stdout</tt>
6741 #
68- # # Single sided stem-plot
69- # UnicodePlot.stemplot(words_1)
70- #
71- # # Back to back stem-plot
72- # UnicodePlot.stemplot(words_1, words_2)
73- #
74- # # Scaled stem plot using scale=100 (two letters for the stem) and trimmed stems
75- # UnicodePlot.stemplot(words_1, scale: 100, trim: true)
76- #
77- # # Above, but changing the string_padchar
78- # UnicodePlot.stemplot(words_1, scale: 100, trim: true, string_padchar: '?')
42+ # @example Examples using Numbers
43+ # # Generate some numbers
44+ # fifty_floats = 50.times.map { rand(-1000..1000)/350.0 }
45+ # eighty_ints = 80.times.map { rand(1..100) }
46+ # another_eighty_ints = 80.times.map { rand(1..100) }
47+ # three_hundred_ints = 300.times.map { rand(-100..100) }
48+ #
49+ # # Single sided stem-plot
50+ # UnicodePlot.stemplot(eighty_ints)
51+ #
52+ # # Single sided stem-plot with positive and negative values
53+ # UnicodePlot.stemplot(three_hundred_ints)
54+ #
55+ # # Single sided stem-plot using floating point values, scaled
56+ # UnicodePlot.stemplot(fifty_floats, scale: 1)
57+ #
58+ # # Single sided stem-plot using floating point values, scaled with new divider
59+ # UnicodePlot.stemplot(fifty_floats, scale: 1, divider: "😄")
60+ #
61+ # # Back to back stem-plot
62+ # UnicodePlot.stemplot(eighty_ints, another_eighty_ints)
63+ #
64+ # @example Examples using Strings
65+ # # Generate some strings
66+ # words_1 = %w[apple junk ant age bee bar baz dog egg a]
67+ # words_2 = %w[ape flan can cat juice elf gnome child fruit]
68+ #
69+ # # Single sided stem-plot
70+ # UnicodePlot.stemplot(words_1)
71+ #
72+ # # Back to back stem-plot
73+ # UnicodePlot.stemplot(words_1, words_2)
74+ #
75+ # # Scaled stem plot using scale=100 (two letters for the stem) and trimmed stems
76+ # UnicodePlot.stemplot(words_1, scale: 100, trim: true)
77+ #
78+ # # Above, but changing the string_padchar
79+ # UnicodePlot.stemplot(words_1, scale: 100, trim: true, string_padchar: '?')
7980
8081 class Stemplot
8182
83+ # Use {factory} method -- should not be directly called.
8284 def initialize ( *_args , **_kw )
8385 @stemleafs = { }
8486 end
8587
88+ # Factory method to create a Stemplot, creates either a NumericStemplot
89+ # or StringStemplot depending on input.
90+ #
91+ # @param vector [Array] An array of elements to stem-leaf plot
92+ # @return [NumericStemplot] If all elements are Numeric
93+ # @return [StringStemplot] If any elements are not Numeric
8694 def self . factory ( vector , **kw )
8795 vec = Array ( vector )
8896 if vec . all? { |item | item . is_a? ( Numeric ) }
@@ -92,24 +100,34 @@ def self.factory(vector, **kw)
92100 end
93101 end
94102
103+ # Insert a stem and leaf
95104 def insert ( stem , leaf )
96105 @stemleafs [ stem ] ||= [ ]
97106 @stemleafs [ stem ] << leaf
98107 end
99108
109+ # Returns an unsorted list of stems
110+ # @return [Array] Unsorted list of stems
100111 def raw_stems
101112 @stemleafs . keys
102113 end
103114
115+ # Returns a list of leaves for a given stem
116+ # @param stem [Object] The stem
117+ # @return [Array] Unsorted list of leaves
104118 def leaves ( stem )
105119 @stemleafs [ stem ] || [ ]
106120 end
107121
122+ # Determines largest length of any stem
123+ # @return [Integer] Length value
108124 def max_stem_length
109125 @stemleafs . values . map ( &:length ) . max
110126 end
111127
112- # instance method to return sorted list of stems.
128+ # Returns a sorted list of stems
129+ # @param all [Boolean] Return all stems if true, otherwise only return stems if a leaf exists for a stem
130+ # @return [Array] Sorted list of stems
113131 def stems ( all : true )
114132 self . class . sorted_stem_list ( raw_stems , all : all )
115133 end
@@ -129,7 +147,10 @@ def initialize(vector, scale: 10, **kw)
129147 self . insert ( stem , leaf )
130148 end
131149 end
132-
150+
151+ # Print key to STDOUT
152+ # @param scale [Integer] Scale, should be a power of 10
153+ # @param divider [String] Divider character between stem and leaf
133154 def print_key ( scale , divider )
134155 # First print the key
135156 puts "Key: 1#{ divider } 0 = #{ scale } "
@@ -140,8 +161,10 @@ def print_key(scale, divider)
140161 puts "The decimal is #{ ndigits } digit(s) to the #{ right_or_left } of #{ divider } "
141162 end
142163
143- # class method to return sorted list of stems.
144- # used when we have stems from a dual-plot
164+ # Used when we have stems from a back-to-back stemplot and a combined list of stems is given
165+ # @param stems [Array] Concatenated list of stems from two plots
166+ # @param all [Boolean] Return all stems if true, otherwise only return stems if a leaf exists for a stem
167+ # @return [Array] Sorted list of stems
145168 def self . sorted_stem_list ( stems , all : true )
146169 negkeys , poskeys = stems . partition { |str | str [ 0 ] == '-' }
147170 if all
@@ -174,19 +197,18 @@ def initialize(vector, scale: 10, string_padchar: '_', **_kw)
174197 end
175198 end
176199
177- def print_key ( scale , divider )
200+ # Function prototype to provide same interface as {NumericStemplot}.
201+ # This function does not do anything.
202+ # @return [false]
203+ def print_key ( _scale , _divider )
178204 # intentionally empty
179205 return false
180- # First print the key
181- puts ""
182- puts "Key: 1#{ divider } 0 = #{ scale } "
183- # Description of where the decimal is
184- trunclog = Math . log10 ( scale ) . truncate
185- ndigits = trunclog . abs
186- right_or_left = ( trunclog < 0 ) ? "left" : "right"
187- puts "The decimal is #{ ndigits } digit(s) to the #{ right_or_left } of #{ divider } "
188206 end
189207
208+ # Used when we have stems from a back-to-back stemplot and a combined list of stems is given
209+ # @param stems [Array] Concatenated list of stems from two plots
210+ # @param all [Boolean] Return all stems if true, otherwise only return stems if a leaf exists for a stem
211+ # @return [Array] Sorted list of stems
190212 def self . sorted_stem_list ( stems , all : true )
191213 if all
192214 rmin , rmax = stems . minmax
@@ -197,7 +219,17 @@ def self.sorted_stem_list(stems, all: true)
197219 end
198220
199221 end
200- # single-vector stemplot
222+
223+ # Print a Single-Vector stemplot to STDOUT.
224+ #
225+ # - Stem data is printed on the left.
226+ # - Leaf data is printed on the right.
227+ # - Key is printed at the bottom.
228+ # @param plt [Stemplot] Stemplot object
229+ # @param scale [Integer] Scale, should be a power of 10
230+ # @param divider [String] Divider character between stem and leaf
231+ # @param padchar [String] Padding character
232+ # @param trim [Boolean] Trim missing stems from the plot
201233 def stemplot1! ( plt ,
202234 scale : 10 ,
203235 divider : "|" ,
@@ -218,7 +250,18 @@ def stemplot1!(plt,
218250 plt . print_key ( scale , divider )
219251 end
220252
221- # back-to-back stemplot
253+ # Print a Back-to-Back Stemplot to STDOUT
254+ #
255+ # - +plt1+ Leaf data is printed on the left.
256+ # - Common stem data is printed in the center.
257+ # - +plt2+ Leaf data is printed on the right.
258+ # - Key is printed at the bottom.
259+ # @param plt1 [Stemplot] Stemplot object for the left side
260+ # @param plt2 [Stemplot] Stemplot object for the right side
261+ # @param scale [Integer] Scale, should be a power of 10
262+ # @param divider [String] Divider character between stem and leaf
263+ # @param padchar [String] Padding character
264+ # @param trim [Boolean] Trim missing stems from the plot
222265 def stemplot2! ( plt1 , plt2 ,
223266 scale : 10 ,
224267 divider : "|" ,
@@ -244,7 +287,39 @@ def stemplot2!(plt1, plt2,
244287
245288 end
246289
247- # Single or Double
290+ # Generates one or more {Stemplot} objects from the input data
291+ # and prints a Single or Double stemplot using {stemplot1!} or {stemplot2!}
292+ # @see Stemplot
293+ # @example Single sided stemplot
294+ # >> UnicodePlot.stemplot(eighty_ints)
295+ # 0 | 257
296+ # 1 | 00335679
297+ # 2 | 034455899
298+ # 3 | 145588
299+ # 4 | 0022223
300+ # 5 | 0223399
301+ # 6 | 012345568889
302+ # 7 | 01133334466777888
303+ # 8 | 013689
304+ # 9 | 22667
305+ # Key: 1|0 = 10
306+ # The decimal is 1 digit(s) to the right of |
307+ #
308+ # @example Back-to-back stemplot
309+ # >> UnicodePlot.stemplot(eighty_ints, another_eighty_ints)
310+ # 752 | 0 | 1244457899
311+ # 97653300 | 1 | 4799
312+ # 998554430 | 2 | 015668
313+ # 885541 | 3 | 0144557888899
314+ # 3222200 | 4 | 00268
315+ # 9933220 | 5 | 0234778
316+ # 988865543210 | 6 | 122222357889
317+ # 88877766443333110 | 7 | 134556689
318+ # 986310 | 8 | 24589
319+ # 76622 | 9 | 022234468
320+ # Key: 1|0 = 10
321+ # The decimal is 1 digit(s) to the right of |
322+ #
248323 def stemplot ( *args , scale : 10 , **kw )
249324 case args . length
250325 when 1
0 commit comments