- Never ever use length, because what it measures depends on the size of the input array. Always use size or numel.
- sort(array, 'ascend'); sorts the array and then discards the output because you do not allocate it to anything. It also sorts over the columns, or the first non-singleton dimension: this is likely not what you expect.
- sum(array) does not sum all values in an array, it sums over the columns, or the first non-singleton dimensions: this is likely not what you expect.
- To fix the previous two points you should use (:) indexing first.
- You do not need to use an if statement, using round is simpler.
- Always read the error messages: is mod(array/2) really a supported syntax?
How to use any size array as an input?
26 views (last 30 days)
Show older comments
I need to make a function that calculates the median and mean values of an array. I'm not sure how to use an array as an input when it needs to be able to be any dimensions. Also, matlab is giving me the error, "too many input arguments" for the mod function, not quite sure why. Here is my code:
function [meanValue, medianValue] = statsFunction(array)
sort(array, 'ascend');
if mod(length(array), 2) ~= 0
medianValue = (length(array)/2)+1;
elseif mod(array/2) == 0
medianValue = ((length(array)/2) + ((length(array)/2)+1))/length(array);
end
meanValue = sum(array)/length(array);
4 Comments
Stephen23
on 20 Feb 2018
Edited: Stephen23
on 21 Dec 2018
length is an abomination: do not use it.
One day a bright-eyed user decides to loop over the columns of a matrix, and because they only have a few rows they use length:
>> length(zeros(3,8))
ans = 8
and everything looks hunky-dory: length returned the number of columns of the matrix, which is perfect for their code. But the next day their user inputs an array with more rows than the one that the code was tested with:
>> length(zeros(99,8))
ans = 99
Oh no! length no longer returns the number of columns, it now returns the number of rows! Suddenly their code in the loop tries to access columns that do not exist, it throws an error and they can't figure out why, because, well, yesterday everything worked and they didn't change anything! Confusion reigns, tears flow, there is a great gnashing of teeth, and questions to random strangers on internet forums...
If only they had used size, which always measures exactly the requested dimension, they would have avoided some pointless debugging: to get the number of columns they just needed size(array,2), and this will always return the number of columns, no matter the size of the array.
For much the same reasons, to get the total number of elements in an array use numel.
Jan
on 20 Feb 2018
@Kristen: As Stephen has written already, use size or numel:
doc size
doc numel
See this example:
A = rand(2, 3)
Now length() replies 3, because it is the length of the longest dimension. But this is rarely useful, except if you are sure that the array is a vector. size(A, 2) is accurate to determine the length of the 2nd dimension, numel(A) replies 6, the total number of elements.
Answers (2)
Guillaume
on 20 Feb 2018
If not for the bugs, your function would work for vector inputs of any size (but not matrices or arrays, i.e. anything with 2 or more dimensions).
You're calculating the index of the median value, not the median value itself.
mod(array/2) is certainly not the same thing as |mod(length(array), 2)). It's no wonder you get an error for the former.
In any case
if somecondition
%do something
elseeif ~somecondition
%do something else
end
is redundant, if the if is false, then the elseif has to be true. So it can be simplified to:
if condition
%do something
else
%do something else
end
It's not clear what your function is supposed to do with arrays that are not vector or even if it's supposed to work with arbitrary sized arrays. If it is only meant to support vectors, I would add a check as a first line:
validateattributes(array, {'numeric'}, {'vector'});
Finally, note that your sort line is pointless since you don't assign the result to anything.
Jan
on 20 Feb 2018
Edited: Jan
on 20 Feb 2018
If you want to consider all elements and not the shape of the array:
function [meanValue, medianValue] = statsFunction(array)
x = array(:);
...
Now x is a column-vector containing all elements of the input array.
s = sort(x);
This assigns the sorted vector x to s. Of course you can combine the commands:
s = sort(array(:));
In your code
medianValue = (length(array)/2)+1;
you calculate the index of the element containing the median value, but I assume you want the value of the element:
ns = numel(s); % Avoid repeated calls of numel() for clarity
if mod(ns, 2) % You can omit: ~= 0
medianValue = s((ns + 1) / 2);
else
...
This should help you to find the median for an even number of elements also. Use the values s at the indices ns/2 and ns/2+1. Divide by 2, not by the number of elements.
0 Comments
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!