Clear Filters
Clear Filters

average over a certain range of index ?

77 views (last 30 days)
Megha
Megha on 14 Feb 2021
Edited: Jan on 15 Feb 2021
I have vector A = [1 7 12 20 23 31]; and B = [6 11 19 22 30 35].
now i want to average another matrix C with 1x35 elements over the index range "1:6, 7:11, 12:19, 20:22, 23:30, 30:35".
is it possible to do something like mean(C(A:B))?? However this does not work. Can anyone please help in this regard.?
  1 Comment
Jan
Jan on 14 Feb 2021
Edited: Jan on 14 Feb 2021
How large are the inputs? Can the intervals overlap? Is A(2:end) and B(1:end-1)+1 equal in every case?

Sign in to comment.

Answers (4)

randerss simil
randerss simil on 14 Feb 2021
clear
clc
A = [1 7 12 20 23 31];
B = [6 11 19 22 30 35];
C = rand(1,35)
for i = 1:numel(A)
kk(i) = mean(C(A(i):B(i)));
end
  1 Comment
Megha
Megha on 14 Feb 2021
randerss simil thank you so much for your reply.
Unfortunately, this is my last option... I know this stuff... but i wanted to do it quickly without using FOR loop...

Sign in to comment.


Jan
Jan on 14 Feb 2021
Edited: Jan on 14 Feb 2021
nC = 1e6; % Number of elements of C
nA = 1e5; % Number of intervals
C = rand(1, nC); % Test data
% Create indices: ----------------------
% non-overlapping intervals with gaps
% v = sort(randperm(nC, nA * 2));
% A = v(1:2:end);
% B = v(2:2:end);
% overlapping:
v = sort(randi([1, nC], nA, 2), 2);
A = v(:, 1);
B = min(v(:, 2), A + 100); % Maximum width: 101
% non-overlapping without gaps:
% B = [sort(randperm(1e6-1, 1e5-1)), 1e6];
% A = [1, B(1:end-1) + 1];
tic;
for i = 1:numel(A)
kk1(i) = mean(C(A(i):B(i)));
end
toc
tic;
kk2 = zeros(1, numel(A));
for i = 1:numel(A)
kk2(i) = mean(C(A(i):B(i)));
end
toc
tic;
kk3 = zeros(1, numel(A));
for i = 1:numel(A)
kk3(i) = sum(C(A(i):B(i))) / (B(i)-A(i)+1);
end
toc
isequal(kk1, kk2, kk3) % Yes, the outputs are identical
The timings:
% Elapsed time is 0.211296 seconds. No pre-allocation
% Elapsed time is 0.185444 seconds. With pre-allocation
% Elapsed time is 0.014207 seconds. SUM/Len instead of MEAN
This shows, that mean() is the bottleneck of the standard approach.
[EDITED] I'm working on a C-Mex version, which is 10 times faster. I'm going to publish it in the FEX.

Image Analyst
Image Analyst on 14 Feb 2021
Megha, here is a non-for loop way of doing it using splitapply():
A = [1 7 12 20 23 31];
B = [6 11 19 22 30 35];
C = rand(1,35)
% Method 1 : using splitapply() and no for loop:
% Create group labels.
r = repelem(1:length(A), B - A + 1)
% Get the mean of each group.
theMeans = splitapply(@mean, C, r)
% Method 2 : for loop.
% Double check first method by comparing to the for loop method:
for i = 1:numel(A)
kk(i) = mean(C(A(i):B(i)));
end
kk % Report to command window. The values are the same, as expected.
  1 Comment
Jan
Jan on 14 Feb 2021
Edited: Jan on 15 Feb 2021
splitapply calls accumarry internally. Then this is a shortcut:
m = accumarray(r.', C, [], @mean);
Calling the function handle @mean is surpringly slower than SUM/Len. Some timings:
% Dense and not overlapping intervals:
C = rand(1, 1e6);
B = [sort(randperm(1e6-1, 1e5-1)), 1e6];
A = [1, B(1:end-1) + 1];
tic;
r = repelem(1:length(A), B - A + 1);
m1 = splitapply(@mean, C, r);
toc
tic;
r = repelem(1:length(A), B - A + 1);
m2 = accumarray(r.', C, [], @mean);
toc
tic; % Implicit @sum and specify the output size:
r = repelem(1:length(A), B - A + 1);
m3 = accumarray(r.', C, [numel(A), 1]) ./ (B(:) - A(:) + 1);
toc
isequal(m1(:), m2, m3) % true
% R2018b, Win10, Intel i7
% Elapsed time is 2.463368 seconds. SPLITAPPLY
% Elapsed time is 0.927217 seconds. ACCUMARRAY(@mean)
% Elapsed time is 0.009275 seconds. ACCUMARRAY(sum) ./ Len
Factor 265 faster than splitapply and factor 100 compared to @mean.

Sign in to comment.


Jan
Jan on 14 Feb 2021
Edited: Jan on 14 Feb 2021
Another method assuming, that the intervals are dense and not overlapping:
A = [1 7 12 20 23 31];
B = [6 11 19 22 30 35]; % A(2:end) == B(1:end-1) + 1 !!!
C = rand(1,35)
S = cumsum(C);
SB = S(B);
kk = [SB(1), diff(SB)] ./ (B - A + 1)
This is less accurate for large C, because cumsum accumulates rounding errors.
Timings:
C = rand(1, 1e6);
% Dense and not overlapping intervals:
B = [sort(randperm(1e6-1, 1e5-1)), 1e6];
A = [1, B(1:end-1) + 1];
tic;
kk3 = zeros(1, numel(A));
for i = 1:numel(A)
kk1(i) = sum(C(A(i):B(i))) / (B(i)-A(i)+1);
end
toc
tic
S = cumsum(C);
SB = S(B);
kk2 = [SB(1), diff(SB)] ./ (B - A + 1);
toc
max(abs(kk1 - kk2)) % 2.91e-11 !!! Is this sufficient?!
Timings:
% Elapsed time is 0.040201 seconds. Loop SUM/Len
% Elapsed time is 0.004538 seconds. CUMSUM (rounding limitations!)
% Elapsed time is 0.009275 seconds. ACCUMARRAY SUM/Len
% Elapsed time is 0.002097 seconds. C-Mex (published soon)

Categories

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