Indexing Error - can't get for loop to function because indices are incorrect

function basis = regbas(CorrectionType)
basisN0 = @(x)[ 1 ];
basisN1 = @(x)[ 1, x ];
basisN2 = @(x)[ 1, x, x^2 ];
basisN3 = @(x)[ 1, x, x^2, x^3 ];
if strcmp(CorrectionType,'Constant')
basis = basisN0
elseif strcmp(CorrectionType,'Linear')
basis = basisN1
elseif strcmp(CorrectionType,'Quadratic')
basis = basisN2
elseif strcmp(CorrectionType,'Cubic')
basis = basisN3
else
disp("Error - CorrectionType should be either 'Constant', 'Linear', 'Quadratic' or 'Cubic'.")
end
end
This function defines "basis"
function coef = alsqr(arr,basis)
x = arr(:,1); % time is column 1
y = arr(:,2); % change second value for column based on which acceleration data you're using
if length(x) ~= length(y); disp('Error - The dimensions of the x and y value lists in the data are not the same')
end
order = length(basis(1));
n = length(x);
A = ones(n,order);
for ORD = 1:order
vec = basis(ORD);
for dat = 1:n
A(dat, ORD) = vec(x(dat)); % ERROR OCCURS HERE
end
end
AT = A';
AA = AT*A;
Ay = AT*y;
w = AA\Ay;% same as inv(AA)*Ay;
coef = round(w,9);
end
I am looking to create a matrix "A" that has length(x) rows and the same number of columns as basis. When I run this function (alsqr), I get an error inside the second for loop telling me "Array indices must be positive integers or logical values." I have tried many different formats and can't get it to run correctly. These functions are to solve for a least squares regression.

 Accepted Answer

regbas returns a function handle. Presumably it is that function handle that is being passed into alsqr
x = arr(:,1); % time is column 1
So x is expected to be a vector of times.
order = length(basis(1));
Invoking the function handle on scalar input 1 returns a vector, and you are calculating the length of the vector returned. Reasonable code.
for ORD = 1:order
vec = basis(ORD);
You are passing the current order, such as 1, 2, 3, to basis(), which is accepting those as x values and returning a vector of values. ORD = 1 might return [1, 1, 1^2], ORD = 2 might return [1, 2, 2^2] and so on. So vec will be a numeric vector of length order
for dat = 1:n
A(dat, ORD) = vec(x(dat)); % ERROR OCCURS HERE
x is a vector of times. x(dat) is a scalar time, such as 0.013 . You then use that scalar time, which will not generally be a positive integer, to try to index vec, which is numeric vector of integers like [1, 3, 9] . But those times are not valid subscripts.
Reminder that your basis is not a vector of function handles to be indexed and individually applied to data: your basis is a function handle to something that returns a vector. As in
A = cell2mat(arrayfun(basis, x(:), 'uniform', 0));

5 Comments

You would not even need the arrayfun if you were to vectorize your basis, such as
basisN3 = @(x)[ ones(size(x(:)), x(:), x(:).^2, x(:).^3 ];
This worked perfectly! Thank you. I have not used arrayfun before, what does 'uniform' do?
Also, it seems that vectorizing the basis as such would be a bit less accurate. However, the arrayfun worked well.
Vectorizing the basis will not be less accurate.
uniform false: arrayfun returns the outputs of func in cell arrays. The outputs of func can have any sizes and different data types.
format long g
x = randn(50,1) * 1000;
basisN3 = @(x)[ 1, x, x^2, x^3 ];
basisN3v = @(x) [ones(size(x(:))), x(:), x(:).^2, x(:).^3];
A1 = cell2mat(arrayfun(basisN3, x, 'uniform', 0));
A2 = basisN3v(x);
size(A1)
ans = 1×2
50 4
size(A2)
ans = 1×2
50 4
max(abs(A1(:) - A2(:)))
ans =
0
isequal(A1, A2)
ans = logical
1
Bit. For. Bit. Identical.
What led you to suspect that the vectorized version might be less accurate?
I must have run it incorrectly. Following what you provided here, I see that it does work very well. Thank you again.

Sign in to comment.

More Answers (0)

Products

Release

R2019a

Community Treasure Hunt

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

Start Hunting!