## Copyright (C) 2007-2017 David Bateman ## ## This file is part of Octave. ## ## Octave is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or (at ## your option) any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, see ## . ## -*- texinfo -*- ## @deftypefn {} {} mode (@var{x}) ## @deftypefnx {} {} mode (@var{x}, @var{dim}) ## @deftypefnx {} {[@var{m}, @var{f}, @var{c}] =} mode (@dots{}) ## Compute the most frequently occurring value in a dataset (mode). ## ## @code{mode} determines the frequency of values along the first non-singleton ## dimension and returns the value with the highest frequency. If two, or ## more, values have the same frequency @code{mode} returns the smallest. ## ## If the optional argument @var{dim} is given, operate along this dimension. ## ## The return variable @var{f} is the number of occurrences of the mode in ## the dataset. ## ## The cell array @var{c} contains all of the elements with the maximum ## frequency. ## @seealso{mean, median} ## @end deftypefn function [m, f, c] = mode (x, dim) if (nargin < 1 || nargin > 2) print_usage (); endif if (! (isnumeric (x) || islogical (x))) error ("mode: X must be a numeric vector or matrix"); endif nd = ndims (x); sz = size (x); if (nargin < 2) ## Find the first non-singleton dimension. (dim = find (sz > 1, 1)) || (dim = 1); else if (! (isscalar (dim) && dim == fix (dim) && dim > 0)) error ("mode: DIM must be an integer and a valid dimension"); endif endif if (isempty (x)) %% codepath for Matlab compatibility. empty x produces NaN output, but %% m f and c shape depends on size of x. if ((nargin == 1) && (nd == 2) && (sz == [0 0])) f = 0; %seems to always be a double even if x is single if (isa (x, "single")) m = single (NaN); c = {(single (NaN (0, 1)))}; else m = NaN; c = {(NaN (0, 1))}; endif else if (nargin == 2) sz(dim) = 1; else sz (find ((sz ~= 1), 1)) = 1; endif f = zeros (sz); %seems to always be a double even if x is single if (isa (x, "single")) m = single (NaN (sz)); c = cell (sz); c(:) = {(single (NaN (1, 0)))}; else m = NaN (sz); c = cell (sz); c(:) = {(NaN (1, 0))}; endif endif return endif if (dim > nd) ## Special case of mode over non-existent dimension. m = x; f = ones (size (x)); c = num2cell (x); return; endif sz2 = sz; sz2(dim) = 1; sz3 = ones (1, nd); sz3(dim) = sz(dim); if (issparse (x)) t2 = sparse (sz(1), sz(2)); else t2 = zeros (sz); endif if (dim != 1) perm = [dim, 1:dim-1, dim+1:nd]; t2 = permute (t2, perm); endif xs = sort (x, dim); t = cat (dim, true (sz2), diff (xs, 1, dim) != 0); if (dim != 1) t2(permute (t != 0, perm)) = diff ([find(permute (t, perm))(:); prod(sz)+1]); f = max (ipermute (t2, perm), [], dim); xs = permute (xs, perm); else t2(t) = diff ([find(t)(:); prod(sz)+1]); f = max (t2, [], dim); endif c = cell (sz2); if (issparse (x)) m = sparse (sz2(1), sz2(2)); else m = zeros (sz2, class (x)); endif for i = 1 : prod (sz2) c{i} = xs(t2(:, i) == f(i), i); m(i) = c{i}(1); endfor endfunction %!test %! [m, f, c] = mode (toeplitz (1:5)); %! assert (m, [1, 2, 2, 2, 1]); %! assert (f, [1, 2, 2, 2, 1]); %! assert (c, {[1; 2; 3; 4; 5], [2], [2; 3], [2], [1; 2; 3; 4; 5]}); %!test %! [m, f, c] = mode (toeplitz (1:5), 2); %! assert (m, [1; 2; 2; 2; 1]); %! assert (f, [1; 2; 2; 2; 1]); %! assert (c, {[1; 2; 3; 4; 5]; [2]; [2; 3]; [2]; [1; 2; 3; 4; 5]}); %!test %! a = sprandn (32, 32, 0.05); %! sp0 = sparse (0); %! [m, f, c] = mode (a); %! [m2, f2, c2] = mode (full (a)); %! assert (m, sparse (m2)); %! assert (f, sparse (f2)); %! c_exp(1:length (a)) = { sp0 }; %! assert (c , c_exp); %! assert (c2, c_exp); %!assert (mode ([2, 3, 1, 2, 3, 4] ,1), [2, 3, 1, 2, 3, 4]) %!assert (mode ([2, 3, 1, 2, 3, 4], 2), 2) %!assert (mode ([2, 3, 1, 2, 3, 4]), 2) %!assert (mode (single ([2, 3, 1, 2, 3, 4])), single (2)) %!assert (mode (int8 ([2, 3, 1, 2, 3, 4])), int8 (2)) %!assert (mode ([2; 3; 1; 2; 3; 4], 1), 2) %!assert (mode ([2; 3; 1; 2; 3; 4], 2), [2; 3; 1; 2; 3; 4]) %!assert (mode ([2; 3; 1; 2; 3; 4]), 2) %!test %! x = magic (3); %! [m, f, c] = mode (x, 3); %! assert (m, x); %! assert (f, ones (3, 3)); %! assert (c, num2cell (x)); %!shared x %! x(:,:,1) = toeplitz (1:3); %! x(:,:,2) = circshift (toeplitz (1:3), 1); %! x(:,:,3) = circshift (toeplitz (1:3), 2); %!test %! [m, f, c] = mode (x, 1); %! assert (reshape (m, [3, 3]), [1 1 1; 2 2 2; 1 1 1]); %! assert (reshape (f, [3, 3]), [1 1 1; 2 2 2; 1 1 1]); %! c = reshape (c, [3, 3]); %! assert (c{1}, [1; 2; 3]); %! assert (c{2}, 2); %! assert (c{3}, [1; 2; 3]); %!test %! [m, f, c] = mode (x, 2); %! assert (reshape (m, [3, 3]), [1 1 2; 2 1 1; 1 2 1]); %! assert (reshape (f, [3, 3]), [1 1 2; 2 1 1; 1 2 1]); %! c = reshape (c, [3, 3]); %! assert (c{1}, [1; 2; 3]); %! assert (c{2}, 2); %! assert (c{3}, [1; 2; 3]); %!test %! [m, f, c] = mode (x, 3); %! assert (reshape (m, [3, 3]), [1 2 1; 1 2 1; 1 2 1]); %! assert (reshape (f, [3, 3]), [1 2 1; 1 2 1; 1 2 1]); %! c = reshape (c, [3, 3]); %! assert (c{1}, [1; 2; 3]); %! assert (c{2}, [1; 2; 3]); %! assert (c{3}, [1; 2; 3]); ## Test input validation %!error mode () %!error mode (1, 2, 3) %!error mode ({1 2 3}) %!error mode (1, ones (2,2)) %!error mode (1, 1.5) %!error mode (1, 0) ## Tests for empty input Matlab compatibility (bug #48690) %!test %! [m, f, c] = mode ([]); %! assert (m, NaN); %! assert (f, 0); %! assert (c, {(NaN (0, 1))}); %!test %! [m, f, c] = mode (single ([])); %! assert (m, single (NaN)); %! assert (f, double (0)); %! assert (c, {(single (NaN (0, 1)))}); %!test %! [m, f, c] = mode (ones (0, 1)); %! assert (m, NaN); %! assert (f, 0); %! assert (c, {(NaN (1, 0))}); %!test %! [m, f, c] = mode (ones (1, 0)); %! assert (m, NaN); %! assert (f, 0); %! assert (c, {(NaN (1, 0))}); %!test %! [m, f, c] = mode (single (ones (1, 0))); %! assert (m, single (NaN)); %! assert (f, double (0)); %! assert (c, {(single (NaN (1, 0)))}); %!test %! [m, f, c] = mode (ones (2, 0)); %! assert (m, NaN (1, 0)); %! assert (f, zeros (1, 0)); %! assert (c, cell (1, 0)); %!test %! [m, f, c] = mode (ones (0, 2)); %! assert (m, NaN (1, 2)); %! assert (f, zeros (1, 2)); %! assert (c, {(NaN (1, 0)),(NaN (1, 0))}); %!test %! [m, f, c] = mode (single (ones (2, 0))); %! assert (m, single (NaN (1, 0))); %! assert (f, zeros (1, 0)); %! assert (c, cell (1, 0)); %!test %! [m, f, c] = mode (ones (0, 0, 1, 0)); %! assert (m, NaN (1, 0, 1, 0)); %! assert (f, zeros (1, 0, 1, 0)); %! assert (c, cell (1, 0, 1, 0)); %!test %! [m, f, c] = mode (ones (1, 1, 1, 0)); %! assert (m, NaN (1, 1)); %! assert (f, zeros (1, 1)); %! assert (c, {(NaN (1, 0))}); %!assert (mode (ones (0, 0, 0, 0)), NaN (1, 0, 0, 0)) %!assert (mode (ones (0, 0, 0, 1)), NaN (1, 0, 0, 1)) %!assert (mode (ones (0, 0, 0, 2)), NaN (1, 0, 0, 2)) %!assert (mode (ones (0, 0, 1, 0)), NaN (1, 0, 1, 0)) %!assert (mode (ones (0, 0, 1, 1)), NaN (1, 1, 1, 1)) %!assert (mode (ones (0, 0, 1, 2)), NaN (1, 0, 1, 2)) %!assert (mode (ones (0, 0, 2, 0)), NaN (1, 0, 2, 0)) %!assert (mode (ones (0, 0, 2, 1)), NaN (1, 0, 2, 1)) %!assert (mode (ones (0, 0, 2, 2)), NaN (1, 0, 2, 2)) %!assert (mode (ones (0, 1, 0, 0)), NaN (1, 1, 0, 0)) %!assert (mode (ones (0, 1, 0, 1)), NaN (1, 1, 0, 1)) %!assert (mode (ones (0, 1, 0, 2)), NaN (1, 1, 0, 2)) %!assert (mode (ones (0, 1, 1, 0)), NaN (1, 1, 1, 0)) %!assert (mode (ones (0, 1, 1, 1)), NaN (1, 1, 1, 1)) %!assert (mode (ones (0, 1, 1, 2)), NaN (1, 1, 1, 2)) %!assert (mode (ones (0, 1, 2, 0)), NaN (1, 1, 2, 0)) %!assert (mode (ones (0, 1, 2, 1)), NaN (1, 1, 2, 1)) %!assert (mode (ones (0, 1, 2, 2)), NaN (1, 1, 2, 2)) %!assert (mode (ones (0, 2, 0, 0)), NaN (1, 2, 0, 0)) %!assert (mode (ones (0, 2, 0, 1)), NaN (1, 2, 0, 1)) %!assert (mode (ones (0, 2, 0, 2)), NaN (1, 2, 0, 2)) %!assert (mode (ones (0, 2, 1, 0)), NaN (1, 2, 1, 0)) %!assert (mode (ones (0, 2, 1, 1)), NaN (1, 2, 1, 1)) %!assert (mode (ones (0, 2, 1, 2)), NaN (1, 2, 1, 2)) %!assert (mode (ones (0, 2, 2, 0)), NaN (1, 2, 2, 0)) %!assert (mode (ones (0, 2, 2, 1)), NaN (1, 2, 2, 1)) %!assert (mode (ones (0, 2, 2, 2)), NaN (1, 2, 2, 2)) %!assert (mode (ones (1, 0, 0, 0)), NaN (1, 1, 0, 0)) %!assert (mode (ones (1, 0, 0, 1)), NaN (1, 1, 0, 1)) %!assert (mode (ones (1, 0, 0, 2)), NaN (1, 1, 0, 2)) %!assert (mode (ones (1, 0, 1, 0)), NaN (1, 1, 1, 0)) %!assert (mode (ones (1, 0, 1, 1)), NaN (1, 1, 1, 1)) %!assert (mode (ones (1, 0, 1, 2)), NaN (1, 1, 1, 2)) %!assert (mode (ones (1, 0, 2, 0)), NaN (1, 1, 2, 0)) %!assert (mode (ones (1, 0, 2, 1)), NaN (1, 1, 2, 1)) %!assert (mode (ones (1, 0, 2, 2)), NaN (1, 1, 2, 2)) %!assert (mode (ones (1, 1, 0, 0)), NaN (1, 1, 1, 0)) %!assert (mode (ones (1, 1, 0, 1)), NaN (1, 1, 1, 1)) %!assert (mode (ones (1, 1, 0, 2)), NaN (1, 1, 1, 2)) %!assert (mode (ones (1, 1, 1, 0)), NaN (1, 1, 1, 1)) %!assert (mode (ones (1, 1, 2, 0)), NaN (1, 1, 1, 0)) %!assert (mode (ones (1, 2, 0, 0)), NaN (1, 1, 0, 0)) %!assert (mode (ones (1, 2, 0, 1)), NaN (1, 1, 0, 1)) %!assert (mode (ones (1, 2, 0, 2)), NaN (1, 1, 0, 2)) %!assert (mode (ones (1, 2, 1, 0)), NaN (1, 1, 1, 0)) %!assert (mode (ones (1, 2, 2, 0)), NaN (1, 1, 2, 0)) %!assert (mode (ones (2, 0, 0, 0)), NaN (1, 0, 0, 0)) %!assert (mode (ones (2, 0, 0, 1)), NaN (1, 0, 0, 1)) %!assert (mode (ones (2, 0, 0, 2)), NaN (1, 0, 0, 2)) %!assert (mode (ones (2, 0, 1, 0)), NaN (1, 0, 1, 0)) %!assert (mode (ones (2, 0, 1, 1)), NaN (1, 0, 1, 1)) %!assert (mode (ones (2, 0, 1, 2)), NaN (1, 0, 1, 2)) %!assert (mode (ones (2, 0, 2, 0)), NaN (1, 0, 2, 0)) %!assert (mode (ones (2, 0, 2, 1)), NaN (1, 0, 2, 1)) %!assert (mode (ones (2, 0, 2, 2)), NaN (1, 0, 2, 2)) %!assert (mode (ones (2, 1, 0, 0)), NaN (1, 1, 0, 0)) %!assert (mode (ones (2, 1, 0, 1)), NaN (1, 1, 0, 1)) %!assert (mode (ones (2, 1, 0, 2)), NaN (1, 1, 0, 2)) %!assert (mode (ones (2, 1, 1, 0)), NaN (1, 1, 1, 0)) %!assert (mode (ones (2, 1, 2, 0)), NaN (1, 1, 2, 0)) %!assert (mode (ones (2, 2, 0, 0)), NaN (1, 2, 0, 0)) %!assert (mode (ones (2, 2, 0, 1)), NaN (1, 2, 0, 1)) %!assert (mode (ones (2, 2, 0, 2)), NaN (1, 2, 0, 2)) %!assert (mode (ones (2, 2, 1, 0)), NaN (1, 2, 1, 0)) %!assert (mode (ones (2, 2, 2, 0)), NaN (1, 2, 2, 0)) %!assert (mode (ones (1, 1, 0, 0, 0)), NaN (1, 1, 1, 0, 0)) %!assert (mode (ones (1, 1, 1, 1, 0)), NaN (1, 1, 1, 1, 1)) %!assert (mode (ones (2, 1, 1, 1, 0)), NaN (1, 1, 1, 1, 0)) %!assert (mode (ones (1, 2, 1, 1, 0)), NaN (1, 1, 1, 1, 0)) ## Tests for empty input with DIM call %!test %! [m, f, c] = mode ([], 1); %! assert (m, NaN (1,0)); %! assert (f, zeros (1,0)); %! assert (c, cell (1,0)); %!test %! [m, f, c] = mode ([], 2); %! assert (m, NaN (0,1)); %! assert (f, zeros (0,1)); %! assert (c, cell (0,1)); %!test %! [m, f, c] = mode ([], 3); %! assert (m, []); %! assert (f, []); %! assert (c, {}); %!test %! [m, f, c] = mode (single([]), 1); %! assert (m, single (NaN (1,0))); %! assert (f, double (zeros (1,0))); %! assert (c, cell (1,0)); %!test %! [m, f, c] = mode (single([]), 2); %! assert (m, single (NaN (0,1))); %! assert (f, double (zeros (0,1))); %! assert (c, cell (0,1)); %!test %! [m, f, c] = mode (single([]), 3); %! assert (m, single([])); %! assert (f, []); %! assert (c, {}); %!test %! [m, f, c] = mode (ones(1,0), 1); %! assert (m, NaN (1,0)); %! assert (f, zeros (1,0)); %! assert (c, cell (1,0)); %!test %! [m, f, c] = mode (ones(1,0), 2); %! assert (m, NaN); %! assert (f, 0); %! assert (c, {(NaN (1,0))}); %!test %! [m, f, c] = mode (ones(1,0), 3); %! assert (m, NaN (1,0)); %! assert (f, zeros (1,0)); %! assert (c, cell (1,0)); %!test %! [m, f, c] = mode (ones(0,1), 1); %! assert (m, NaN); %! assert (f, 0); %! assert (c, {(NaN (1,0))}); %!test %! [m, f, c] = mode (ones(0,1), 2); %! assert (m, NaN (0,1)); %! assert (f, zeros (0,1)); %! assert (c, cell (0,1)); %!test %! [m, f, c] = mode (ones(0,1), 3); %! assert (m, NaN (0,1)); %! assert (f, zeros (0,1)); %! assert (c, cell (0,1)); %!test %! [m, f, c] = mode (ones(0,0,1), 1); %! assert (m, NaN (1,0)); %! assert (f, zeros (1,0)); %! assert (c, cell (1,0)); %!test %! [m, f, c] = mode (ones(0,0,1), 2); %! assert (m, NaN (0,1)); %! assert (f, zeros (0,1)); %! assert (c, cell (0,1)); %!test %! [m, f, c] = mode (ones(0,0,1), 3); %! assert (m, []); %! assert (f, []); %! assert (c, {}); %!test %! [m, f, c] = mode (ones(1,0,1), 1); %! assert (m, NaN (1,0)); %! assert (f, zeros (1,0)); %! assert (c, cell (1,0)); %!test %! [m, f, c] = mode (ones(1,0,1), 2); %! assert (m, NaN); %! assert (f, 0); %! assert (c, {(NaN (1,0))}); %!test %! [m, f, c] = mode (ones(1,0,1), 3); %! assert (m, NaN (1,0)); %! assert (f, zeros (1,0)); %! assert (c, cell (1,0));