Reverse arrangement test - 'undefined operator' error
21 views (last 30 days)
Show older comments
Hello,
I am attempting to build a funtion that returns the 'A' count output of the reverse arrangement test, taking in a user defined Nrec and a vector of random length.
At this point, the code should break a given vector into a user defined number of equal sized blocks - the mean of the values within these blocks is stored as another vector.
Finally, I'm attempting to step through the mean values from these blocks in the new vector to make the comparison count of reverse arrangements...
So far, I think I have a code that should produce what I'm looking for, but I'm presently getting an error :
' Undefined operator '>' for input arguments of type 'cell'.
Error in ReverseArrangementTest (line 58)
if x(ii)>x(jj) '
What can I do to fix this error?
Thanks!
CODE BELOW:
% % Function, "Reverse Arrangement Test" -
% The function receives a random variable as an input (i.e., a vector x) and splits
% it into a user-defined number of sample records (another argument), Nrec, of equal
% length and return the total number of reversals of the mean-square value of each record.
function [A] = ReverseArrangementTest()
% User defined Nrec value input prompt
prompt = 'What is the number of records? ';
Nrec = input(prompt);
% Define the Input Data Set (Or come back and define as another input)
InputDataSet=rand(1, 100)*100;
% Go ahead and square all values to be rid of any negatives...
InputDataSetSq=InputDataSet.^2;
% Detrmine the remainder of th length of the Input Data Set not divisible by
% Nrec
InputLength=length(InputDataSetSq);
Remainder=rem(InputLength,Nrec);
% Truncate Input Data Set to allow it to be grouped into equal size blocks,
% omitting the reamainder of the data not divisable by Nrec
NewLength=(InputLength - Remainder);
SplitInterval=InputLength/Nrec;
SplitInterval = round(SplitInterval, 0);
%display (Nrec)
%display (InputLength)
%display (Remainder)
%display (NewLength)
%display (SplitInterval)
%iCount = size(InputDataSet,2);
iStartIDx = [1:Nrec :NewLength];
for iLoop=1:length(iStartIDx)-1
segment{iLoop} = InputDataSetSq(iStartIDx(iLoop):iStartIDx(iLoop+1)-1);
mn{iLoop} = mean(segment{iLoop});
end
segment{iLoop+1} = InputDataSetSq(iStartIDx(iLoop+1):end);
mn{iLoop+1} = mean(segment{iLoop+1});
%display(iStartIDx)
%display(iLoop)
%display(mn)
x = mn(:); % force the input to be a column vector
%display (x)
N = numel(x);
% Calculation of h
h = zeros(N);
count = 0;
for ii= 1:N
for jj=1:N
while ii<jj
if x(ii)>x(jj)
h(ii,jj) = 1;
else
h(ii,jj) = 0;
end
count = count+1;
if count > N
break
fprintf('loop "while" failed \n');
end
end
end
end
% Calculation of A
A = zeros(1,N-1);
for ii= 1:N
A(ii)= sum(h(ii,ii+1:end));
end
A = sum(A(1:N-1));
0 Comments
Answers (1)
Guillaume
on 2 Feb 2020
First, a few things.
Ideally, processing functions don't ask the user for input. It should be the job of the caller of the function to obtain the inputs whichever way is more appropriate (with input, a GUI, reading from file, the net, a database, etc.). So, the beginning of the function should be:
function A = ReverseArrangementTest(InputDataSet, Nrec) %and with a much more meaningful name for the output
%caller to obtain InputDataSet and Nrec however they want
%...
end
Secondly, don't grow variables in loops. Always preallocate them:
segment = cell(1, numel(StartIdx));
mn = cell(1, numel(StartIdx));
for iLoop=1:length(iStartIDx)-1
%...
However, as we should see shortly, note that loops are rarely needed in matlab and often make the code more complicated than it needs to be.
Thirdly, avoid renaming variables. You have a variable mn, don't rename it x, particularly as x is completely meaningless. It makes it much harder to track what the variables are.
And herein is your problem, mn is a cell array, and therfore so is x. Indeed matlab doesn't know how to compare cell arrays. Since cells of a cell array can contain anything, there can't be a universal comparison operator (e.g. one cell may contain [1, 2, 3], the other 'abcedf'). However, in your case, there's no reason for mn to be a cell array since all each cell contains is a scalar number, so:
mn = zeros(1, numel(StartIdx));
for iLoop = ..
%..
mn(iLoop) = mean(segment{iLoop});
end
%..
mn(iLoop + 1) = ..
But as said, the loop is a complete waste of time. First, pad the vector with NaN so its length is a multiple of Nrec. NaNs don't affect the mean. Then reshape the padded vector in rows of length Nrec. Finally take the mean across the rows. It can all done in one line:
mn = mean(reshape([InputVec, nan(1, rem(numel(InputVec, -Nrec)))], Nrec, 1), 1); %rem(numel, -Nrec) gives the number of pad elements
Similarly, your 2nd double for loop are probably not needed, I'm very unclear on the purpose of the while loop inside there. It doesn't do anything useful since neither ii or jj change inside the while. It will just keep on repeating the same comparison, with the same result, N times. Anyway, the final h is simply:
h = mn > mn.'; %no loop needed. Creates a numel(nm) x numel(nm) symmetric matrix.
And finally, your A is
A = sum(tril(h, -1), 1);
A = sum(A(1:end-1));
0 Comments
See Also
Categories
Find more on Loops and Conditional Statements 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!