How to apply this for-loop containing '<', designed for a scalar array, to several scalar arrays in a cell array?

2 views (last 30 days)
Hello, i have the code below which was designed to be applied on a 100x6 scalar array called x and contains '>'. I wish to apply it on 4 scalar arrays 100x6 which are in a column as a cell array. Example: Cell :{ [100,6]
[100,6]
[100,6]
[100,6] }
for j=1:6
q=quantile(x(:,j),0.97);
id=find(x(:,j)>(q));
x(id,j)=NaN;
end
Thanks.

Accepted Answer

dpb
dpb on 26 Jun 2022
Edited: dpb on 26 Jun 2022
There was no need for the loop in the original code -- quantile is already vectorized as are almost all ML-supplied functions. The first code should have been written as
Q=0.97; % use variables don't bury magic numbers inside argument lists
q=quantile(x,Q); % find the limit
x(x>q)=nan; % set the exceeding locations
If it is needed to know/have the values of q, then then iterate over the cell array with the above two lines, dereferncing each cell content in turn.
If the values of q aren't needed later, then the whole thing can be turned into a one liner...
x(x>quantile(x,Q))=nan;
and you can iterate over the cell array with the single expression.
But, NOTA BENE: it takes only the loop over the cell array, NOT a double loop as would wrapping the original code in another loop.
Assume the cell array containing the arrays is C --
Q=0.97;
for i=1:numel(C)
q{i}=quantile(C{i}); % compute the quantiles by column
C{i}(C{i}>q{i})=nan; % fixup the cell array
end
NB: the dereferencing of the cell array C with "the curlies" {} to obtain the underlying array, then the subscripting expression inside "regular" parentheses () to address elements within the array.
NB Second: the above overwrites the original cell array; if need to keep the original data, then use another variable to make a copy first before running the loop and use it instead is simplest and fastest (although the original also overwrites so this may be moot point).
See the documentation on cell arrays for the details on the syntax for using and addressing cell arrays.

More Answers (1)

Voss
Voss on 26 Jun 2022
Edited: Voss on 26 Jun 2022
Wrap that loop in another loop:
Cell = { rand(100,6); rand(100,6); rand(100,6); rand(100,6) };
for k = 1:numel(Cell)
x = Cell{k};
for j=1:6
q=quantile(x(:,j),0.97);
id=find(x(:,j)>(q));
x(id,j)=NaN;
end
Cell{k} = x; % store the result back in Cell
end
By the way, if something is scalar, then it can't be 100x6; scalar means 1x1.
  10 Comments
Voss
Voss on 26 Jun 2022
I guess I should've said: to be consistent with the original (loop) code, set the dim argument to 1.
dpb
dpb on 26 Jun 2022
Edited: dpb on 26 Jun 2022
Understand/understood -- I was just being me! :)
It would be consistent with the original coding as done; agreed; I had simply observed that from that code it seemed the case of a single row would have no meaning and so not ever arise in practice but, logically, if it were the case then the only way in which any quantile would have any chance of meaning anything would be over the vector...but it is probably also true that the various columns represent different variables and so mixing across them is also not a reasonable thing to do in practice...
My coding habits would be to have uncovered there being insufficient data on entry into the routine and aborted then before ever getting to this code section.
But, if the intent is only to duplicate the original code logic and make no changes even to edge cases, then the optional argument would do that, yes.

Sign in to comment.

Categories

Find more on Multidimensional Arrays in Help Center and File Exchange

Products


Release

R2018a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!