comparison scripts/plot/stemleaf.m @ 16180:3e6d15a2a50b

Update stemleaf to provide new features and minor fix to printd
author Michael Godfrey <michaeldgodfrey@gmail.com>
date Sat, 02 Mar 2013 18:01:47 -0500
parents 2b994ee38b1c
children 0f0e970723ec
comparison
equal deleted inserted replaced
16179:025393bef399 16180:3e6d15a2a50b
18 ## License along with Octave; see the file COPYING. If not, 18 ## License along with Octave; see the file COPYING. If not,
19 ## see <http://www.gnu.org/licenses/>. 19 ## see <http://www.gnu.org/licenses/>.
20 20
21 21
22 ## -*- texinfo -*- 22 ## -*- texinfo -*-
23 ## @deftypefn {Function File} {} stemleaf (@var{x}) 23 ## @deftypefn {Function File} {} stemleaf (@var{x}, @var{caption})
24 ## @deftypefnx {Function File} {@var{plot} =} stemleaf (@var{x}, @var{opt}) 24 ## @deftypefnx {Function File} {} stemleaf (@var{x}, @var{caption}, @var{stem_sz})
25 ## 25 ## @deftypefnx {Function File} {@var{plotstr} =} stemleaf (@dots{})
26 ## Compute and display a stem and leaf plot of the vector @var{x}. 26 ## Compute and display a stem and leaf plot of the vector @var{x}.
27 ## 27 ##
28 ## The @var{x} vector is converted to integer by @var{x} = @code{fix} (@var{x}). 28 ## The input @var{x} should be a vector of integers. Any non-integer values
29 ## If an output argument is provided, the plot is returned as 29 ## will be converted to integer by @code{@var{x} = fix (@var{x})}. By default
30 ## an array of strings. The first element is the heading 30 ## each element of @var{x} will be plotted with the last digit of the element
31 ## followed by an element for each stem. 31 ## as a leaf value and the remaining digits as the stem. For example, 123
32 ## The default stem step is 10. 32 ## will be plotted with the stem @samp{12} and the leaf @samp{3}. The second
33 ## The @var{x} vector should be integers. It will be treated so that 33 ## argument, @var{caption}, should be a char array which provides a description
34 ## the last digit is the leaf value and the other digits are 34 ## of the data. It is included as a heading for the output.
35 ## the stems. 35 ##
36 ## The leaf digits are not sorted. If sorted leaf values 36 ## The optional input @var{stem_sz} sets the width of each stem.
37 ## are wanted, use @code{sort} (@var{x}) before calling @code{stemleaf} (@var{x}). 37 ## The stem width is determined by @code{10^(@var{stem_sz} + 1)}.
38 ## The stem and leaf plot is described in: Ch. 3, 38 ## The default stem width is 10.
39 ## Exploratory Data Analysis by J. W. Tukey, Addison-Wesley, 1977. 39 ##
40 ## The output of stemleaf is composed of two parts: a "Fenced Letter Display,"
41 ## followed by the stem-and-leaf plot itself. The Fenced Letter Display is
42 ## described in @cite{Exploratory Data Analysis}. Briefly, the entries
43 ## are as shown:
44 ## @example
45 ## @group
46 ##
47 ## Fenced Letter Display
48 ## #% nx|___________________ nx = numel (x)
49 ## M% mi| md | mi median index, md median
50 ## H% hi|hl hu| hs hi lower hinge index, hl,hu hinges, hs h_spread
51 ## 1 |x(1) x(nx)| x(1), x(nx) first and last data value
52 ## _______
53 ## ______|step |_______ step 1.5*h_spread
54 ## f|ifl ifh| inner fence, lower and higher
55 ## |nfl nfh| # data points within fences
56 ## F|ofl ofh| outer fence, lower and higher
57 ## |nFl nFh| # data points outside outer fences
58 ## @end group
59 ## @end example
60 ##
61 ## The stem-and-leaf plot shows on each line the stem value followed by the
62 ## string made up of the leaf digits. If the @var{stem_sz} is not 1 the
63 ## successive leaf values are separated by ",".
64 ##
65 ## With no return argument, the plot is immediately displayed. If an output
66 ## argument is provided, the plot is returned as an array of strings.
67 ##
68 ## The leaf digits are not sorted. If sorted leaf values are desired, use
69 ## @code{@var{xs} = sort (@var{x})} before calling @code{stemleaf (@var{xs})}.
70 ##
71 ## The stem and leaf plot and associated displays are described in:
72 ## Ch. 3, @cite{Exploratory Data Analysis} by J. W. Tukey, Addison-Wesley, 1977.
40 ## @seealso{hist, printd} 73 ## @seealso{hist, printd}
41 ## @end deftypefn 74 ## @end deftypefn
42 75
43 ## Author: Michael D. Godfrey <michaeldgodfrey@gmail.com> 76 ## Author: Michael D. Godfrey <michaeldgodfrey@gmail.com>
44 ## Description: Compute stem and leaf plot 77 ## Description: Compute stem and leaf plot
45 78
46 function varargout = stemleaf (x, stem_unit) 79 function plotstr = stemleaf (x, caption, stem_sz)
47 ## Compute and display a stem and leaf plot of the vector x. The x 80 ## Compute and display a stem and leaf plot of the vector x. The x
48 ## vector is converted to integer by x = fix(x). If an output argument 81 ## vector is converted to integer by x = fix(x). If an output argument
49 ## is provided, the plot is returned as an array of strings. The 82 ## is provided, the plot is returned as an array of strings. The
50 ## first element is the heading followed by an element for each stem. 83 ## first element is the heading followed by an element for each stem.
51 ## 84 ##
52 ## The default stem step is 10. If stem_unit is provided the stem 85 ## The default stem step is 10. If stem_sz is provided the stem
53 ## step is set to: 10^(stem_unit+1) The x vector should be integers. 86 ## step is set to: 10^(stem_sz+1). The x vector should be integers.
54 ## It will be treated so that the last digit is the leaf value and the 87 ## It will be treated so that the last digit is the leaf value and the
55 ## other digits are the stems. 88 ## other digits are the stems.
56 ## 89 ##
57 ## When we first implemented stem and leaf plots in the early 1960's 90 ## When we first implemented stem and leaf plots in the early 1960's
58 ## there was some discussion about sorting vs. leaving the leaf 91 ## there was some discussion about sorting vs. leaving the leaf
59 ## entries in the original order in the data. We decided in favor or 92 ## entries in the original order in the data. We decided in favor of
60 ## sorting the leaves for most purposes. This is the choice 93 ## sorting the leaves for most purposes. This is the choice
61 ## implemented in the SNAP/IEDA system that was written at that time. 94 ## implemented in the SNAP/IEDA system that was written at that time.
62 ## 95 ##
63 ## SNAP/IEDA and particularly its stem and leaf plotting were further 96 ## SNAP/IEDA, and particularly its stem and leaf plotting, were further
64 ## developed by Hale Trotter, David Hoagland (at Princeton and MIT) 97 ## developed by Hale Trotter, David Hoagland (at Princeton and MIT),
65 ## and others. 98 ## and others.
66 ## 99 ##
67 ## Tukey, in EDA, generally uses unsorted leaves. In addition, he 100 ## Tukey, in EDA, generally uses unsorted leaves. In addition, he
68 ## described a wide range of additional display formats. This 101 ## described a wide range of additional display formats. This
69 ## implementation does not sort the leaves, but if the x vector is 102 ## implementation does not sort the leaves, but if the x vector is
76 ## array of strings with each row containing a line of the plot 109 ## array of strings with each row containing a line of the plot
77 ## preceded by the lines of header text as the first row. This 110 ## preceded by the lines of header text as the first row. This
78 ## facilitates annotation. 111 ## facilitates annotation.
79 ## 112 ##
80 ## Note that the code has some added complexity due to the need to 113 ## Note that the code has some added complexity due to the need to
81 ## distinguish both + and - 0 stems. The +- stem values are essential 114 ## distinguish both + and - 0 stems. The +- stem values are essential
82 ## for all plots which span 0. After dealing with +-0 stems, the added 115 ## for all plots which span 0. After dealing with +-0 stems, the added
83 ## complexity of putting +- data values in the correct stem is minor, 116 ## complexity of putting +- data values in the correct stem is minor,
84 ## but the sign of 0 leaves must be checked. And, the cases where the 117 ## but the sign of 0 leaves must be checked. And, the cases where the
85 ## stems start or end at +- 0 must also be considered. 118 ## stems start or end at +- 0 must also be considered.
86 ## 119 ##
87 ## The fact that IEEE floating point defines +- 0 helps make this 120 ## The fact that IEEE floating point defines +- 0 helps make this
88 ## easier. 121 ## easier.
89 ## 122 ##
90 ##
91 ## Michael D. Godfrey January 2013 123 ## Michael D. Godfrey January 2013
92 124
93 ## More could be implemented for better data scaling. And, of course, 125 ## More could be implemented for better data scaling. And, of course,
94 ## other options for the kinds of plots described by Tukey could be 126 ## other options for the kinds of plots described by Tukey could be
95 ## provided. This may best be left to users. 127 ## provided. This may best be left to users.
96 128
97 if (nargin >= 2) 129 if (nargin < 2 || nargin > 3)
98 stem_step = 10^(stem_unit+1); 130 print_usage ();
131 endif
132
133 if (! isvector (x))
134 error ("stemleaf: X must be a vector");
135 endif
136
137 if (! ischar (caption))
138 error ("stemleaf: CAPTION must be a character array");
139 endif
140
141 if (isinteger (x))
142 ## Avoid use of integers because rounding rules do not use fix():
143 ## Example: floor (int32 (-44)/10) == -4, floor (int32 (-46)/10) = -5 !!!
144 x = single (x);
145 elseif (isfloat (x))
146 xint = fix (x);
147 if (any (x != xint))
148 warning ("stemleaf: X truncated to integer values");
149 x = xint;
150 endif
99 else 151 else
152 error ("stemleaf: X must be a numeric vector");
153 endif
154
155 if (nargin == 2)
156 stem_sz = 0;
100 stem_step = 10; 157 stem_step = 10;
101 endif 158 else
102 if (any (x == int32 (x)) == 0) 159 if (isscalar (stem_sz) && stem_sz >= 0 && isreal (stem_sz))
103 printf ('Input vector truncated to integer values.\n') 160 stem_sz = fix (stem_sz);
104 x = fix (x); 161 stem_step = 10^(stem_sz+1);
105 endif 162 else
106 163 error ("stemleaf: STEM_SZ must be a real integer >= 0");
107 ## Avoid use of int32 due to: 164 endif
108 165 endif
109 ## floor (int32 (-44)/10) == -4 and floor (int32 (-46)/10) = -5 !!!
110 ## x = sort (fix (x)); % User can decide about sorting x.
111 ## x = fix (x);
112 ## %Adjust scale if too small.
113 ## while any(abs((fix(x) - x)) >= abs(x/100))
114 ## x =10*x;
115 ## endwhile
116 166
117 ## Note that IEEE 754 states that -+ 0 should compare equal. This has 167 ## Note that IEEE 754 states that -+ 0 should compare equal. This has
118 ## led to C sort (and therefore Octave) treating them as equal. Thus, 168 ## led to C sort (and therefore Octave) treating them as equal. Thus,
119 ## sort([ -1 0 -0 1]) yields: -1 0 -0 1. and, sort([-1 -0 0 1]) 169 ## sort([-1 0 -0 1]) yields [-1 0 -0 1], and sort([-1 -0 0 1])
120 ## yields: -1 -0 0 1. This means that stem-and-leaf plotting cannot 170 ## yields: [-1 -0 0 1]. This means that stem-and-leaf plotting cannot
121 ## rely on sort to order the data as needed for display. 171 ## rely on sort to order the data as needed for display.
122 172 ## This also applies to min()/max() so these routines can't be relied
123 if (all((sort(x) == x)) == 1) 173 ## upon if the max or min is -+ 0.
124 hsort = 'sorted.'; 174
175 ## Compute hinges and fences based on ref: EDA pgs. 33 and 44.
176 ## Note that these outlier estimates are meant to be "distribution free".
177
178 nx = numel (x);
179 xs = sort (x); # Note that sort preserves -0
180 mdidx = fix ((nx + 1)/2); # median index
181 hlidx = fix ((mdidx + 1)/2); # lower hinge index
182 huidx = fix (nx + 1 - hlidx); # upper hinge index
183 md = xs(mdidx); # median
184 hl = xs(hlidx); # lower hinge
185 hu = xs(huidx); # upper hinge
186 h_spread = hu - hl; # h_spread: difference between hinges
187 step = 1.5*h_spread; # step: 1.5 * h_spread
188 i_fence_l = hl - step; # inner fences: outside hinges + step
189 o_fence_l = hl - 2*step; # outer fences: outside hinges + 2*step
190 i_fence_h = hu + step;
191 o_fence_h = hu + 2*step;
192 n_out_l = sum (x<i_fence_l) - sum (x<o_fence_l);
193 n_out_h = sum (x>i_fence_h) - sum (x>o_fence_h);
194 n_far_l = sum (x<o_fence_l);
195 n_far_h = sum (x>o_fence_h);
196
197 # display table similar to that on pg. 33
198 plot_out = sprintf(" Data: %s", caption);
199 plot_out = [plot_out; sprintf(" ")];
200 plot_out = [plot_out; sprintf(" Fenced Letter Display")];
201 plot_out = [plot_out; sprintf(" ")];
202 plot_out = [plot_out; sprintf(" #%3d|___________________", nx)];
203 plot_out = [plot_out; sprintf(" M%3d| %5d |", mdidx, md)];
204 plot_out = [plot_out; sprintf(" H%3d|%5d %5d| %d", hlidx, hl, hu, h_spread)];
205 plot_out = [plot_out; sprintf(" 1 |%5d %5d|", xs(1), xs(nx))];
206 plot_out = [plot_out; sprintf(" _______")];
207 plot_out = [plot_out; sprintf(" ______|%5d|_______",step)];
208 plot_out = [plot_out; sprintf(" f|%5d %5d|", i_fence_l, i_fence_h)];
209 plot_out = [plot_out; sprintf(" |%5d %5d| out", n_out_l, n_out_h)];
210 plot_out = [plot_out; sprintf(" F|%5d %5g|", o_fence_l, o_fence_h)];
211 plot_out = [plot_out; sprintf(" |%5d %5d| far",n_far_l,n_far_h)];
212 plot_out = [plot_out; " "];
213
214 ## Determine stem values
215 min_x = min (x);
216 max_x = max (x);
217 if (min_x > 0) # all stems > 0
218 stems = [fix(min(x)/stem_step) : (fix(max(x)/stem_step)+1)];
219 elseif (max_x < 0) # all stems < 0
220 stems = [(fix(min_x/stem_step)-1) : fix(max_x/stem_step)];
221 if (stems(end) == 0)
222 stems(end) = -0; # Fix signbit on 0 lost by ':' operator
223 endif
224 elseif (min_x < 0 && max_x > 0) # range crosses 0
225 stems = [(fix(min_x/stem_step)-1) : -1 , -0];
226 stems = [stems, 0 : fix(max_x/stem_step)+1 ];
227 else # one endpoint is a zero which may be +0 or -0
228 if (min_x == 0)
229 if (any (x == 0 & signbit (x)))
230 min_x = -0;
231 else
232 min_x = +0;
233 endif
234 endif
235 if (max_x == 0)
236 if (any (x == 0 & ! signbit (x)))
237 max_x = +0;
238 else
239 max_x = -0;
240 endif
241 endif
242 stems = [];
243 if (signbit (min_x))
244 stems = [(fix(min_x/stem_step)-1) : -1 , -0];
245 endif
246 if (! signbit (max_x))
247 stems = [stems, 0 : fix(max_x/stem_step)+1 ];
248 endif
249 endif
250
251 if (issorted (x))
252 hsort = "sorted.";
125 else 253 else
126 hsort = 'unsorted.'; 254 hsort = "unsorted.";
127 endif 255 endif
128 nx = max (size (x)); 256
129 ## Determine stem values 257 ## Vectorized version provided by Rik Webring (Rik@ortave.org)
130 if (min(x) < 0) 258 ## Determine leaves for each stem:
131 if (signbit(max(x)) == 0) # max is positive 259 prev_line = "none";
132 stems = [fix(min(x)/stem_step)-1 : -1 -0]; 260 new_line = 1;
133 stems = [stems 0 : fix(max(x)/stem_step)+1 ]; 261 for kx = 2: numel (stems)
262
263 stem_sign = signbit (stems(kx));
264 if (stems(kx) <= 0)
265 idx = ((x <= stems(kx)*stem_step) & (x > (stems(kx-1)*stem_step))
266 & (signbit (x) == stem_sign));
267 xlf = abs (x(idx) - stems(kx)*stem_step);
134 else 268 else
135 if (max(x) < 0) 269 idx = ((x < stems(kx)*stem_step) & (x >= (stems(kx-1)*stem_step))
136 stems = [(fix(min(x)/stem_step)-1) : fix(max(x)/stem_step)]; 270 & (signbit (x) == stem_sign));
137 else 271 xlf = abs (x(idx) - stems(kx-1)*stem_step);
138 stems = [(fix(min(x)/stem_step)-1) : -1 -0]; 272 endif
139 stems = [stems 0 : fix(max(x)/stem_step)]; 273 ## Convert leaves to a string
140 endif 274 if (stem_sz == 0)
141 endif 275 lf_str = sprintf ("%d", xlf);
142 else # All stems are > 0
143 stems = [fix(min(x)/stem_step) : fix(max(x)/stem_step) + 1];
144 endif
145 ##stems
146 ##x
147 nstems = max(size(stems));
148 ## compute hinges at +- 1.5 * quartiles
149 ## this requires sorted data!
150 xs = sort (x); # Note that sort preserves -0
151 threeh = 1.5;
152 two = 2.0;
153 j = idivide(nx, 4, "fix") + 1; # Use F95 truncation.
154 k = nx - j + 1;
155 hl = xs (j);
156 hu = xs (k);
157 if ( (nx + 1) == (4 * j) )
158 hl = (xs (j + 1) + hl) / two;
159 hu = (xs (k - 1) + hu) / two;
160 endif
161
162 ## :::::::: determine h-spread (dh) and fences ::::::::
163 dh = hu - hl;
164 fu = hu + threeh * dh;
165 fl = hl - threeh * dh;
166
167 ## :::::::: find value adjacent to lower fence ::::::::
168 for i = 1:j
169 if ( xs (i) >= fl )
170 continue;
171 endif
172 endfor
173 ilow = i;
174 xlo = xs (ilow);
175
176 ## :::::::: find value adjacent to upper fence ::::::::
177 for i = 1:j
178 if ( xs (nx -i + 1) <= fu )
179 continue;
180 endif
181 endfor
182
183 ihi = nx - i + 1;
184 xhi = xs (ihi);
185
186 ## Heading for output:
187 plot_out = "";
188 plot_out = [plot_out sprintf("stem step: %i, data: %s\nHinges: lo: %g, hi: %g\n",
189 stem_step, hsort, xlo, xhi)];
190
191 ## This may appear to be a good place to use vectorization using the
192 ## stem and data arrays but the necessary special case treatment of 0
193 ## and -0 seems to result in little reduction of complexity, and since
194 ## this algorithm is for small data vectors only there would be
195 ## practically no performance improvement.
196
197 ## Determine leaves for each stem:
198 for kx = 2:nstems
199 line_out = "";
200 steml = "";
201 ## Build a string of leaf digits for stem(kx) if stem(kx) <= 0, or
202 ## stem(kx-1) if stem(kx) > 0
203
204 ## stems -+ 0 have to be handled as special cases.
205 for xi = 1:nx
206 if(signbit(stems(kx)) != 0)
207 t1 = ((x(xi) <= stems(kx)*10) && (x(xi) > (stems(kx-1)*10)));
208 else
209 t1 = ((x(xi) < stems(kx)*10) && (x(xi) >= (stems(kx-1)*10)));
210 endif
211 ## Special tests for stem -+ 0
212 if ((stems(kx) == 0) && signbit(stems(kx)) && (x(xi) == 0)) && !signbit(x(xi))
213 t1 = 0;
214 endif
215 if ((stems(kx-1) == 0) && !signbit(stems(kx-1)) && (x(xi) == 0)) && signbit(x(xi))
216 t1 = 0;
217 endif
218 ## Create line as a string
219 if t1
220 if (stems(kx) <= 0)
221 xz = abs (x(xi) - stems(kx)*10);
222 else
223 xz = abs (x(xi) - stems(kx-1)*10);
224 endif
225 if ((stems(kx) == 0) && signbit(stems(kx)))
226 steml = [steml sprintf("%d", abs(x(xi) - stems(kx)*10))];
227 else
228 steml = [steml sprintf("%d", xz)];
229 endif
230 endif % t1
231 endfor % xi = 1:nx
232
233 ## Set correct -0
234 if ((stems(kx) == 0) && signbit(stems(kx)))
235 line_out = [line_out sprintf(" -0 | %s", steml)]; % -0 stem.
236 else 276 else
237 if( stems(kx) < 0) 277 lf_str = "";
238 line_out = [line_out sprintf("%4d | %s", stems(kx), steml)]; 278 if (numel(xlf) > 0)
239 else 279 lf_str = sprintf ("%d", xlf(1,1));
240 if stems(kx) > 0 280 if (numel (xlf) > 1)
241 line_out = [line_out sprintf("%4d | %s", stems(kx-1), steml)]; 281 lf_str = [lf_str sprintf(",%d", xlf(1,2:numel(xlf)))];
242 endif 282 endif
243 endif 283 endif
244 endif 284 endif
245 plot_out = [plot_out; line_out]; 285
246 endfor % kx = 2:nstems 286 ## Set correct -0
287 if (stems(kx) == 0 && signbit (stems(kx)))
288 line = sprintf (" -0 | %s", lf_str); # -0 stem.
289 elseif (stems(kx) < 0)
290 line = sprintf ("%4d | %s", stems(kx), lf_str);
291 elseif (stems(kx) > 0)
292 line = sprintf ("%4d | %s", stems(kx-1), lf_str);
293 else
294 line = "";
295 endif
296
297 if ((!strcmp (lf_str, "")) || (stems(kx) == 0)|| stems(kx-1) == 0)
298 plot_out = [plot_out; line];
299 new_line = 1;
300 else
301 if (new_line == 1)
302 plot_out = [plot_out; " :"]; # just print one : if no leaves
303 new_line = 0;
304 endif
305 endif
306
307 endfor # kx = 2: numel (stems)
247 if (nargout == 0) 308 if (nargout == 0)
248 rows = size (plot_out)(1); 309 disp (plot_out);
249 cols = size (plot_out)(2);
250 for k = 1:rows
251 printf("%s\n", plot_out(k,1:cols));
252 endfor
253 else 310 else
254 varargout{1} = plot_out; 311 plotstr = plot_out;
255 endif 312 endif
256 endfunction 313 endfunction
314
257 315
258 %!demo 316 %!demo
259 %! ## Unsorted plot: 317 %! ## Unsorted plot:
260 %! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44]; 318 %! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44];
261 %! stemleaf (x, 0); 319 %! stemleaf (x, "Unsorted plot");
262 320
263 %!demo 321 %!demo
264 %! ## Sorted leaves: 322 %! ## Sorted leaves:
265 %! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44]; 323 %! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44];
266 %! y = sort(x); 324 %! y = sort (x);
267 %! stemleaf (y, 0); 325 %! stemleaf (y, "Sorted leaves");
268 326
269 %!demo 327 %!demo
270 %! ## More data (sorted) 328 %! ## Sorted leaves (large dataset):
271 %! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127 36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58 114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31 115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57 122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0 ]; 329 %! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127 \
272 %! y = sort(x); 330 %! 36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 \
273 %! stemleaf (y, 0); 331 %! 23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58 \
332 %! 114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31 \
333 %! 115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57\
334 %! 122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 \
335 %! 127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0];
336 %! y = sort (x);
337 %! stemleaf (y, "Sorted leaves (large dataset)");
338
339 %!demo
340 %! ## Gaussian leaves:
341 %! x = fix (30 * randn (300,1));
342 %! stemleaf (x);
274 343
275 %!test 344 %!test
276 %! ## test minus to plus 345 %! ## test minus to plus
277 %! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127 36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58 114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31 115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57 122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0 ]; 346 %! x = [-22 12 -28 52 39 -2 12 10 11 11 42 38 44 18 44 37 113 124 37 48 127 \
278 %! x = sort(x); 347 %! 36 29 31 125 139 131 115 105 132 104 123 35 113 122 42 117 119 58 109 \
279 %! r2 = ["stem step: 10, data: sorted.\nHinges: lo: 30, hi: 116\n";... 348 %! 23 105 63 27 44 105 99 41 128 121 116 125 32 61 37 127 29 113 121 58 \
280 %! " -2 | 82";" -1 | 3";" -0 | 2";" 0 | 00177";... 349 %! 114 126 53 114 96 25 109 7 31 141 46 -13 71 43 117 116 27 7 68 40 31 \
281 %! " 1 | 00112288";" 2 | 001133577777899";... 350 %! 115 124 42 128 52 71 118 117 38 27 106 33 117 116 111 40 119 47 105 57\
282 %! " 3 | 000111123456777889";" 4 | 00122233344456788";... 351 %! 122 109 124 115 43 120 43 27 27 18 28 48 125 107 114 34 133 45 120 30 \
283 %! " 5 | 223788";" 6 | 138";" 7 | 11";" 8 | ";... 352 %! 127 31 116 146 21 23 30 10 20 21 30 0 100 110 1 20 0];
284 %! " 9 | 69";" 10 | 04555567999";" 11 | 0133344455566667777899";... 353 %! x = sort (x);
285 %! " 12 | 0011223444555677788";" 13 | 1239";" 14 | 16"]; 354 %! rexp = char (
286 %! rx = stemleaf (x, 0); 355 %! " Data: test minus to plus" ,
287 %! assert(r2, rx); 356 %! " " ,
357 %! " Fenced Letter Display" ,
358 %! " " ,
359 %! " #138|___________________" ,
360 %! " M 69| 52 |" ,
361 %! " H 35| 30 116| 86" ,
362 %! " 1 | -28 146|" ,
363 %! " _______" ,
364 %! " ______| 129|_______" ,
365 %! " f| -99 245|" ,
366 %! " | 0 0| out" ,
367 %! " F| -228 374|" ,
368 %! " | 0 0| far" ,
369 %! " " ,
370 %! " -2 | 82" ,
371 %! " -1 | 3" ,
372 %! " -0 | 2" ,
373 %! " 0 | 00177" ,
374 %! " 1 | 00112288" ,
375 %! " 2 | 001133577777899" ,
376 %! " 3 | 000111123456777889" ,
377 %! " 4 | 00122233344456788" ,
378 %! " 5 | 223788" ,
379 %! " 6 | 138" ,
380 %! " 7 | 11" ,
381 %! " : " ,
382 %! " 9 | 69" ,
383 %! " 10 | 04555567999" ,
384 %! " 11 | 0133344455566667777899",
385 %! " 12 | 0011223444555677788" ,
386 %! " 13 | 1239" ,
387 %! " 14 | 16" );
388 %! r = stemleaf (x, "test minus to plus", 0);
389 %! assert (r, rexp);
390
288 %!test 391 %!test
289 %! ## positive values above 0 392 %! ## positive values above 0
290 %! x = [22 12 28 52 39 12 11 11 42 38 44 18 44 ]; 393 %! x = [5 22 12 28 52 39 12 11 11 42 38 44 18 44];
291 %! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: 12, hi: 42\n";... 394 %! rexp = char (
292 %! " 1 | 22118";" 2 | 28";" 3 | 98";" 4 | 244";" 5 | 2"]; 395 %! " Data: positive values above 0" ,
293 %! rx = stemleaf (x, 0); 396 %! " " ,
294 %! assert(r2, rx); 397 %! " Fenced Letter Display" ,
398 %! " " ,
399 %! " # 14|___________________" ,
400 %! " M 7| 22 |" ,
401 %! " H 4| 12 42| 30" ,
402 %! " 1 | 5 52|" ,
403 %! " _______" ,
404 %! " ______| 45|_______" ,
405 %! " f| -33 87|" ,
406 %! " | 0 0| out" ,
407 %! " F| -78 132|" ,
408 %! " | 0 0| far" ,
409 %! " " ,
410 %! " 0 | 5" ,
411 %! " 1 | 22118" ,
412 %! " 2 | 28" ,
413 %! " 3 | 98" ,
414 %! " 4 | 244" ,
415 %! " 5 | 2" );
416 %! r = stemleaf (x, "positive values above 0");
417 %! assert (r, rexp);
418
295 %!test 419 %!test
296 %! ## negative values below 0 420 %! ## negative values below 0
297 %! x = [22 12 28 52 39 12 11 11 42 38 44 18 44]; 421 %! x = [5 22 12 28 52 39 12 11 11 42 38 44 18 44];
298 %! x = -x; 422 %! x = -x;
299 %! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: -42, hi: -12\n";... 423 %! rexp = char (
300 %! " -5 | 2";" -4 | 244";" -3 | 98";" -2 | 28";" -1 | 22118"]; 424 %! " Data: negative values below 0" ,
301 %! rx = stemleaf (x, 0); 425 %! " " ,
302 %! assert(r2, rx); 426 %! " Fenced Letter Display" ,
427 %! " " ,
428 %! " # 14|___________________" ,
429 %! " M 7| -28 |" ,
430 %! " H 4| -42 -12| 30" ,
431 %! " 1 | -52 -5|" ,
432 %! " _______" ,
433 %! " ______| 45|_______" ,
434 %! " f| -87 33|" ,
435 %! " | 0 0| out" ,
436 %! " F| -132 78|" ,
437 %! " | 0 0| far" ,
438 %! " " ,
439 %! " -5 | 2" ,
440 %! " -4 | 244" ,
441 %! " -3 | 98" ,
442 %! " -2 | 28" ,
443 %! " -1 | 22118" ,
444 %! " -0 | 5" );
445 %! r = stemleaf (x, "negative values below 0");
446 %! assert (r, rexp);
447
303 %!test 448 %!test
304 %! ## positive values from 0 449 %! ## positive values from 0
305 %! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44]; 450 %! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44];
306 %! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: 11, hi: 42\n";... 451 %! rexp = char (
307 %! " 0 | 20";" 1 | 22118";" 2 | 28";" 3 | 98";" 4 | 244";" 5 | 2"]; 452 %! " Data: positive values from 0" ,
308 %! rx = stemleaf (x, 0); 453 %! " " ,
309 %! assert(r2, rx); 454 %! " Fenced Letter Display" ,
455 %! " " ,
456 %! " # 15|___________________" ,
457 %! " M 8| 22 |" ,
458 %! " H 4| 11 42| 31" ,
459 %! " 1 | 0 52|" ,
460 %! " _______" ,
461 %! " ______| 46|_______" ,
462 %! " f| -35 88|" ,
463 %! " | 0 0| out" ,
464 %! " F| -82 135|" ,
465 %! " | 0 0| far" ,
466 %! " " ,
467 %! " 0 | 20" ,
468 %! " 1 | 22118" ,
469 %! " 2 | 28" ,
470 %! " 3 | 98" ,
471 %! " 4 | 244" ,
472 %! " 5 | 2" );
473 %! r = stemleaf (x, "positive values from 0");
474 %! assert (r, rexp);
475
310 %!test 476 %!test
311 %! ## negative values from 0 477 %! ## negative values from 0
312 %! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44]; 478 %! x = [22 12 28 52 39 2 12 0 11 11 42 38 44 18 44];
313 %! x = -x; 479 %! x = -x;
314 %! r2 = ["stem step: 10, data: unsorted.\nHinges: lo: -42, hi: -11\n";... 480 %! rexp = char (
315 %! " -5 | 2";" -4 | 244";" -3 | 98";" -2 | 28";" -1 | 22118";" -0 | 20"]; 481 %! " Data: negative values from 0" ,
316 %! rx = stemleaf (x, 0); 482 %! " " ,
317 %! assert(r2, rx); 483 %! " Fenced Letter Display" ,
318 484 %! " " ,
485 %! " # 15|___________________" ,
486 %! " M 8| -22 |" ,
487 %! " H 4| -42 -11| 31" ,
488 %! " 1 | -52 0|" ,
489 %! " _______" ,
490 %! " ______| 46|_______" ,
491 %! " f| -88 35|" ,
492 %! " | 0 0| out" ,
493 %! " F| -135 82|" ,
494 %! " | 0 0| far" ,
495 %! " " ,
496 %! " -5 | 2" ,
497 %! " -4 | 244" ,
498 %! " -3 | 98" ,
499 %! " -2 | 28" ,
500 %! " -1 | 22118" ,
501 %! " -0 | 20" );
502 %! r = stemleaf (x, "negative values from 0");
503 %! assert (r, rexp);
504
505 %!test
506 %! ## both +0 and -0 present
507 %! x = [-9 -7 -0 0 -0];
508 %! rexp = char (
509 %! " Data: both +0 and -0 present" ,
510 %! " " ,
511 %! " Fenced Letter Display" ,
512 %! " " ,
513 %! " # 5|___________________" ,
514 %! " M 3| 0 |" ,
515 %! " H 2| -7 0| 7" ,
516 %! " 1 | -9 0|" ,
517 %! " _______" ,
518 %! " ______| 10|_______" ,
519 %! " f| -17 10|" ,
520 %! " | 0 0| out" ,
521 %! " F| -28 21|" ,
522 %! " | 0 0| far" ,
523 %! " " ,
524 %! " -0 | 9700" ,
525 %! " 0 | 0" );
526 %! r = stemleaf (x, "both +0 and -0 present");
527 %! assert (r, rexp);
528
529 %!test
530 %! ## both <= 0 and -0 present
531 %! x = [-9 -7 0 -0];
532 %! rexp = char (
533 %! " Data: both <= 0 and -0 present" ,
534 %! " " ,
535 %! " Fenced Letter Display" ,
536 %! " " ,
537 %! " # 4|___________________" ,
538 %! " M 2| -7 |" ,
539 %! " H 1| -9 0| 9" ,
540 %! " 1 | -9 0|" ,
541 %! " _______" ,
542 %! " ______| 13|_______" ,
543 %! " f| -22 13|" ,
544 %! " | 0 0| out" ,
545 %! " F| -36 27|" ,
546 %! " | 0 0| far" ,
547
548 %! " " ,
549 %! " -0 | 970" ,
550 %! " 0 | 0" );
551 %! r = stemleaf (x, "both <= 0 and -0 present");
552 %! assert (r, rexp);
553
554 %!test
555 %! ## Example from EDA: Chevrolet Prices pg. 30
556 %! x = [150 250 688 695 795 795 895 895 895 1099 1166 1333 1499 1693 1699 1775 1995];
557 %! rexp = char (
558 %! " Data: Chevrolet Prices EDA pg.30",
559 %! " " ,
560 %! " Fenced Letter Display" ,
561 %! " " ,
562 %! " # 17|___________________" ,
563 %! " M 9| 895 |" ,
564 %! " H 5| 795 1499| 704" ,
565 %! " 1 | 150 1995|" ,
566 %! " _______" ,
567 %! " ______| 1056|_______" ,
568 %! " f| -261 2555|" ,
569 %! " | 0 0| out" ,
570 %! " F|-1317 3611|" ,
571 %! " | 0 0| far" ,
572 %! " " ,
573 %! " 1 | 50" ,
574 %! " 2 | 50" ,
575 %! " :" ,
576 %! " 6 | 88,95" ,
577 %! " 7 | 95,95" ,
578 %! " 8 | 95,95,95" ,
579 %! " :" ,
580 %! " 10 | 99" ,
581 %! " 11 | 66" ,
582 %! " :" ,
583 %! " 13 | 33" ,
584 %! " 14 | 99" ,
585 %! " :" ,
586 %! " 16 | 93,99" ,
587 %! " 17 | 75" ,
588 %! " :" ,
589 %! " 19 | 95" );
590
591 %! r = stemleaf(x, "Chevrolet Prices EDA pg.30", 1);
592 %! assert (r, rexp);
593
594 ## Test input validation
595 %!error stemleaf ()
596 %!error stemleaf (1, 2, 3, 4)
597 %!error <X must be a vector> stemleaf (ones (2,2), "")
598 %!warning <X truncated to integer values> tmp = stemleaf ([0 0.5 1],"");
599 %!error <X must be a numeric vector> stemleaf ("Hello World", "data")
600 %!error <STEM_SZ must be a real integer> stemleaf (1, "", ones (2,2))
601 %!error <STEM_SZ must be a real integer> stemleaf (1, "", -1)
602 %!error <STEM_SZ must be a real integer> stemleaf (1, "", 1+i)