Skip to content

Commit 146fb6e

Browse files
authored
Merge pull request #49 from nanobowers/issue48_stemplot_doc
Reformat stemplot document
2 parents 836ea74 + 4f5f2c8 commit 146fb6e

2 files changed

Lines changed: 148 additions & 69 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@ Gemfile.lock
22
pkg/
33
tmp/
44
*~
5+
6+
# to prevent yard documentation from accidentally being checked in
7+
.yardoc/
8+
doc/

lib/unicode_plot/stemplot.rb

Lines changed: 144 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,31 @@
22

33
module 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

Comments
 (0)