# Subset of an array with a moving window

2 views (last 30 days)
Alex Nickerson on 16 Apr 2021
Edited: Alex Nickerson on 16 Apr 2021
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 CommentsShowHide 1 older comment
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.

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
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.