How to Calculate Moving Product?
4 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Gaurav Soni
il 18 Dic 2015
Commentato: Gaurav Soni
il 8 Gen 2020
Is there any vectorized way of calculating moving products. If A is a vector, how can I calculate its moving product with a specified window size.
For example, for a window size of 3, the moving product should be equal to:
[A(3)*A(2)*A(1), A(4)*A(3)*A(2), A(5)*A(4)*A(3), ..., A(N)*A(N-1)*A(N-2)]
How do I calculate it without using a for loop. I know that the 'filter' function can be used for calculating moving means in a vectorized manner; but I have not seen any function that can calculate a moving product.
Can someone please help. Thanks.
1 Commento
Guido Marco
il 27 Giu 2016
try somthing like this... function Y=divf(X) % divisive differential
X0=X(1:end-1); X1=X(2:end); Y=X1./X0;
Risposta accettata
Più risposte (3)
Guillaume
il 18 Dic 2015
One way to achieve what you want:
function mp = movingproduct(v, windowsize)
%add input validation code
vv = repmat([v(:); nan], 1, windowsize);
vv = reshape(vv(1:end-windowsize), [], windowsize);
mp = prod(vv(windowsize:end, :), 2);
if isrow(v), mp = mp.'; end
end
2 Commenti
Guillaume
il 19 Dic 2015
Modificato: Guillaume
il 21 Mag 2016
Another possible implementation, which has no numerical errors. It does have a loop (through arrayfun) but only over the window size.
function mp = movingproduct(v, windowsize)
%add input validation code
vv = repmat({v(:)}, 1, windowsize);
vv = arrayfun(@(row) circshift(vv{row}, row-1), 1:windowsize, 'UniformOutput', false);
vv = [vv{:}];
mp = prod(vv(windowsize:end, :), 2);
if isrow(v), mp = mp.'; end
end
Image Analyst
il 19 Dic 2015
One possibility is to use nlfilter() where you can define the filter to be used on the window to do absolutely anything you want it to do, such as prod().
output = nlfilter(yourMatrix, [1, 3], @prod);
I attach a full blown demo where I use nlfilter to compute the Otsu threshold on a sliding 3x3 window basis.
Mark Britten-Jones
il 21 Mag 2016
Modificato: Guillaume
il 21 Mag 2016
The problem with the loop approach is that it repeats calculations. For example A(3)*A(2) is calculated twice in a moving product of window size 3. The vectorised versions also suffer from this repetition. It can be avoided using a recursive approach which recognises that e.g. for k even a k moving product can be calculates as a k/2 moving product times the k/2 lag of the k/2 moving product. For large k the increases in speed are dramatic. Here is the code, which relies on a lag function (few lines to code up):
function y = cumprodk(x,k)
y = x;
if k==1; return; end;
y = cumprodk(y, floor(k/2));
y = lag(y, floor(k/2)).*y;
if rem(k,2) == 1 % if k odd need to multiply by lag k-1
y = lag(x,k-1).*y;
end
end
Thats it. No loops and faster for large k
0 Commenti
Vedere anche
Categorie
Scopri di più su Install Products in Help Center e File Exchange
Prodotti
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!