comparison scripts/statistics/base/median.m @ 21540:ffb4770ba079

Make median preserve discrete types (bug #47515). * median.m: Replace mean by "native" sum (or max for logical), and avoid assigning NaN to non-float types. * data.cc (Fnth_element): Allow type bool, treated as an integer.
author Lachlan Andrew <lachlanbis@gmail.com>
date Thu, 24 Mar 2016 13:35:40 +1100
parents a4faec57f4c8
children ecce63c99c3f
comparison
equal deleted inserted replaced
21539:212bafe8413a 21540:ffb4770ba079
39 ## (x(N/2) + x((N/2)+1))/2 N even 39 ## (x(N/2) + x((N/2)+1))/2 N even
40 ## @end group 40 ## @end group
41 ## @end example 41 ## @end example
42 ## 42 ##
43 ## @end ifnottex 43 ## @end ifnottex
44 ## If @var{x} is of a discrete type such as integer or logical, then
45 ## the case of even N rounds up (or toward @qcode{true}).
46 ##
44 ## If @var{x} is a matrix, compute the median value for each column and 47 ## If @var{x} is a matrix, compute the median value for each column and
45 ## return them in a row vector. 48 ## return them in a row vector.
46 ## 49 ##
47 ## If the optional @var{dim} argument is given, operate along this dimension. 50 ## If the optional @var{dim} argument is given, operate along this dimension.
48 ## @seealso{mean, mode} 51 ## @seealso{mean, mode}
78 n = size (x, dim); 81 n = size (x, dim);
79 k = floor ((n+1) / 2); 82 k = floor ((n+1) / 2);
80 if (mod (n, 2) == 1) 83 if (mod (n, 2) == 1)
81 retval = nth_element (x, k, dim); 84 retval = nth_element (x, k, dim);
82 else 85 else
83 retval = mean (nth_element (x, k:k+1, dim), dim); 86 retval = sum (nth_element (x, k:k+1, dim), dim, "native") / 2;
87 if (islogical (x))
88 retval = logical (retval);
89 endif
84 endif 90 endif
85 ## Inject NaNs where needed, to be consistent with Matlab. 91 ## Inject NaNs where needed, to be consistent with Matlab.
86 retval(any (isnan (x), dim)) = NaN; 92 if (isfloat (x))
93 retval(any (isnan (x), dim)) = NaN;
94 endif
87 95
88 endfunction 96 endfunction
89 97
90 98
91 %!test 99 %!test
111 %! x = sort (a, 4); 119 %! x = sort (a, 4);
112 %! y = sort (b, 3); 120 %! y = sort (b, 3);
113 %!assert (median (a, 4), x(:, :, :, 3)) 121 %!assert (median (a, 4), x(:, :, :, 3))
114 %!assert (median (b, 3), (y(:, :, 3, :) + y(:, :, 4, :))/2) 122 %!assert (median (b, 3), (y(:, :, 3, :) + y(:, :, 4, :))/2)
115 123
124 ## Test non-floating point types
125 %!assert (median ([true, false]), true);
126 %!assert (median (uint8 ([1, 3])), uint8 (2));
127 %!assert (median (int8 ([1, 3, 4])), int8 (3));
128 %!assert (median (single ([1, 3, 4])), single (3));
129 %!assert (median (single ([1, 3, NaN])), single (NaN));
130
116 ## Test input validation 131 ## Test input validation
117 %!error median () 132 %!error median ()
118 %!error median (1, 2, 3) 133 %!error median (1, 2, 3)
119 %!error <X must be a numeric> median ({1:5}) 134 %!error <X must be a numeric> median ({1:5})
120 %!error <X cannot be an empty matrix> median ([]) 135 %!error <X cannot be an empty matrix> median ([])