Subset of an array with a moving window

1 view (last 30 days)
I have the following code for computing structure functions. I have provided examples of "ULs" and "UTs" merely for simplicity.
ULs = rand(1,145); % called in from function
UTs = rand(1,145); % called in from function
nrmax = 145; % called in from function, I just happen to be using 145
for nr = 1:nrmax
Nts = numel(ULs); % number of elements
Umat_L = nan(Nts-nr,nr+1); % must be NaN, so zeros() won't work
Umat_T = nan(Nts-nr,nr+1); % must be NaN, so zeros() won't work
for i = 1:(Nts-nr) % this is
Umat_L(i,:)=ULs(i:i+nr); % the for loop
Umat_T(i,:)=UTs(i:i+nr); % I want to remove
end
end
The nested loop thus takes subsets ULs(1:1+nr), then ULs(2:2+nr), ULs(17:17+nr), etc. Is it possible to replicate this subsetting process without using a loop?
It would improve my code run time if I could remove the nested "for i = 1:(Nts-nr)". However, as I see it, there is no way around this because of the nature of the moving window. I tried the following substitution, but it didn't work.
i = (1:Nts-nr);
inr = i + nr;
Umat_L(i,:) = ULs(i:inr);
Umat_T(i,:) = UTs(i:inr);
  2 Comments
Rik
Rik on 16 Apr 2021
Many moving window operations can be replaced by movmean and other mov* functions, or by convolutions. The image processing toolbox also contains several useful functions.
Is this code representative of the result you actually want, or is there a further step in calculation?
Alex Nickerson
Alex Nickerson on 16 Apr 2021
Well, as can be seen in the code, there is no moving mean. I don't have access to the Image Processing Toolbox. I just need to be able to get these variable subsets of the code. I will add some details to the original question to further clarify.

Sign in to comment.

Accepted Answer

Rik
Rik on 16 Apr 2021
The code below relies on implicit expansion to create an index array, which replicates the results from the inner for-loop. Since your code overwrites the results every iteration, you can also have a substantial speed increase by only doing the last one.
nrmax = 145; % called in from function, I just happen to be using 145
ULs = rand(1,nrmax); % called in from function
UTs = rand(1,nrmax); % called in from function
%tic,toc is only an approximate, use timeit for real performance testing
tic,[Umat_L1,Umat_T1]=fun_original(nrmax,ULs,UTs);toc
Elapsed time is 1.689398 seconds.
tic,[Umat_L2,Umat_T2]=fun_unlooped(nrmax,ULs,UTs);toc
Elapsed time is 0.994556 seconds.
if ~isequal(Umat_L1,Umat_L2) || ~isequal(Umat_T1,Umat_T2)
error('results don''t match')
else
disp('everything OK')
end
everything OK
function [Umat_L,Umat_T]=fun_original(nrmax,ULs,UTs)
for slowdown=1:100
for nr = 1:nrmax
Nts = numel(ULs); % number of elements
Umat_L = nan(Nts-nr,nr+1); % must be NaN, so zeros() won't work
Umat_T = nan(Nts-nr,nr+1); % must be NaN, so zeros() won't work
for i = 1:(Nts-nr) % this is
Umat_L(i,:)=ULs(i:i+nr); % the for loop
Umat_T(i,:)=UTs(i:i+nr); % I want to remove
end
end
end
end
function [Umat_L,Umat_T]=fun_unlooped(nrmax,ULs,UTs)
for slowdown=1:100
for nr = 1:nrmax
Nts = numel(ULs); % number of elements
ind=( 0:nr ) + ( 1:(Nts-nr) ).';
Umat_L=ULs(ind);
Umat_T=UTs(ind);
end
end
end
  1 Comment
Alex Nickerson
Alex Nickerson on 16 Apr 2021
Edited: Alex Nickerson on 16 Apr 2021
I have more lines of code that go far beyond the nested loop... I just didn't include them here to save space. This code did exactly what I needed, @Rik, and it cut my code run time (the sample on which I tested it) in half. Thank you for your help.

Sign in to comment.

More Answers (0)

Categories

Find more on Structures 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!