1 ## Copyright (C) 2007-2012 David Bateman
3 ## This file is part of Octave.
5 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or (at
8 ## your option) any later version.
10 ## Octave is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ## General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING. If not, see
17 ## <http://www.gnu.org/licenses/>.
20 ## @deftypefn {Function File} {} mode (@var{x})
21 ## @deftypefnx {Function File} {} mode (@var{x}, @var{dim})
22 ## @deftypefnx {Function File} {[@var{m}, @var{f}, @var{c}] =} mode (@dots{})
23 ## Compute the most frequently occurring value in a dataset (mode).
24 ## @code{mode} determines the frequency of values along the first non-singleton
25 ## dimension and returns the value with the highest frequency. If two, or
26 ## more, values have the same frequency @code{mode} returns the smallest.
28 ## If the optional argument @var{dim} is given, operate along this dimension.
30 ## The return variable @var{f} is the number of occurrences of the mode in
31 ## in the dataset. The cell array @var{c} contains all of the elements
32 ## with the maximum frequency.
33 ## @seealso{mean, median}
36 function [m, f, c] = mode (x, dim)
38 if (nargin < 1 || nargin > 2)
42 if (! (isnumeric (x) || islogical (x)))
43 error ("mode: X must be a numeric vector or matrix");
49 ## Find the first non-singleton dimension.
50 (dim = find (sz > 1, 1)) || (dim = 1);
52 if (!(isscalar (dim) && dim == fix (dim))
53 || !(1 <= dim && dim <= nd))
54 error ("mode: DIM must be an integer and a valid dimension");
64 t2 = sparse (sz(1), sz(2));
70 perm = [dim, 1:dim-1, dim+1:nd];
71 t2 = permute (t2, perm);
75 t = cat (dim, true (sz2), diff (xs, 1, dim) != 0);
78 t2(permute (t != 0, perm)) = diff ([find(permute (t, perm))(:); prod(sz)+1]);
79 f = max (ipermute (t2, perm), [], dim);
80 xs = permute (xs, perm);
82 t2(t) = diff ([find(t)(:); prod(sz)+1]);
83 f = max (t2, [], dim);
88 m = sparse (sz2(1), sz2(2));
90 m = zeros (sz2, class (x));
92 for i = 1 : prod (sz2)
93 c{i} = xs(t2(:, i) == f(i), i);
100 %! [m, f, c] = mode (toeplitz (1:5));
101 %! assert (m, [1,2,2,2,1]);
102 %! assert (f, [1,2,2,2,1]);
103 %! assert (c, {[1;2;3;4;5],[2],[2;3],[2],[1;2;3;4;5]});
105 %! [m, f, c] = mode (toeplitz (1:5), 2);
106 %! assert (m, [1;2;2;2;1]);
107 %! assert (f, [1;2;2;2;1]);
108 %! assert (c, {[1;2;3;4;5];[2];[2;3];[2];[1;2;3;4;5]});
110 %! a = sprandn (32, 32, 0.05);
111 %! [m, f, c] = mode (a);
112 %! [m2, f2, c2] = mode (full (a));
113 %! assert (m, sparse (m2));
114 %! assert (f, sparse (f2));
115 %! c_exp(1:length(a)) = { sparse (0) };
116 %! assert (c ,c_exp);
117 %! assert (c2,c_exp );
119 %!assert(mode ([2,3,1,2,3,4],1),[2,3,1,2,3,4]);
120 %!assert(mode ([2,3,1,2,3,4],2),2);
121 %!assert(mode ([2,3,1,2,3,4]),2);
122 %!assert(mode (single([2,3,1,2,3,4])), single(2));
123 %!assert(mode (int8([2,3,1,2,3,4])), int8(2));
125 %!assert(mode ([2;3;1;2;3;4],1),2);
126 %!assert(mode ([2;3;1;2;3;4],2),[2;3;1;2;3;4]);
127 %!assert(mode ([2;3;1;2;3;4]),2);
130 %! x(:,:,1) = toeplitz (1:3);
131 %! x(:,:,2) = circshift (toeplitz (1:3), 1);
132 %! x(:,:,3) = circshift (toeplitz (1:3), 2);
134 %! [m, f, c] = mode (x, 1);
135 %! assert (reshape (m, [3, 3]), [1 1 1; 2 2 2; 1 1 1]);
136 %! assert (reshape (f, [3, 3]), [1 1 1; 2 2 2; 1 1 1]);
137 %! c = reshape (c, [3, 3]);
138 %! assert (c{1}, [1; 2; 3]);
140 %! assert (c{3}, [1; 2; 3]);
142 %! [m, f, c] = mode (x, 2);
143 %! assert (reshape (m, [3, 3]), [1 1 2; 2 1 1; 1 2 1]);
144 %! assert (reshape (f, [3, 3]), [1 1 2; 2 1 1; 1 2 1]);
145 %! c = reshape (c, [3, 3]);
146 %! assert (c{1}, [1; 2; 3]);
148 %! assert (c{3}, [1; 2; 3]);
150 %! [m, f, c] = mode (x, 3);
151 %! assert (reshape (m, [3, 3]), [1 2 1; 1 2 1; 1 2 1]);
152 %! assert (reshape (f, [3, 3]), [1 2 1; 1 2 1; 1 2 1]);
153 %! c = reshape (c, [3, 3]);
154 %! assert (c{1}, [1; 2; 3]);
155 %! assert (c{2}, [1; 2; 3]);
156 %! assert (c{3}, [1; 2; 3]);
158 %% Test input validation
160 %!error mode (1, 2, 3)
161 %!error mode ({1 2 3})
162 %!error mode (['A'; 'B'])
163 %!error mode (1, ones(2,2))
164 %!error mode (1, 1.5)