필터 지우기
필터 지우기

average over a certain range of index ?

조회 수: 69 (최근 30일)
Megha
Megha 2021년 2월 14일
편집: Jan 2021년 2월 15일
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
Jan
Jan 2021년 2월 14일
편집: Jan 2021년 2월 14일
How large are the inputs? Can the intervals overlap? Is A(2:end) and B(1:end-1)+1 equal in every case?

댓글을 달려면 로그인하십시오.

답변 (4개)

randerss simil
randerss simil 2021년 2월 14일
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
Megha
Megha 2021년 2월 14일
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...

댓글을 달려면 로그인하십시오.


Jan
Jan 2021년 2월 14일
편집: Jan 2021년 2월 14일
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 2021년 2월 14일
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
Jan
Jan 2021년 2월 14일
편집: Jan 2021년 2월 15일
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.

댓글을 달려면 로그인하십시오.


Jan
Jan 2021년 2월 14일
편집: Jan 2021년 2월 14일
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)

카테고리

Help CenterFile Exchange에서 Preprocessing Data에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by