Is it possible to use Arrayfun across rows

17 visualizaciones (últimos 30 días)
William Ambrose
William Ambrose el 6 de Oct. de 2020
Comentada: Mohammad Sami el 8 de Oct. de 2020
Hi,
I currently have a FOR LOOP which works its way through a table with almost 20 million records. It is as expected pretty slow, I want to look into alternatives and I wondered if there is a way to use for arrayfun - or another MATLAB function - across rows which will work with high performance. The example below captures the issue of working across rows:
A = table([1;1;1;2;2;2;],[1;2;3;4;5;6]);
A.Var3 = zeros(height(A),1)
A.Var3(1) = A.Var1(1)
for i = 2:height(A)
if A.Var1(i) == A.Var1(i-1)
A.Var3(i) = A.Var2(i) .* A.Var2(i-1);
else A.Var3(i) = A.Var2(i);
end
end
Any suggestions will be appreciated.
Kind regards,
William
  11 comentarios
Rik
Rik el 6 de Oct. de 2020
The longer the runs are, the more efficient calculating the runs will be. So if you have long stretches of true and/or long stretches of false it might be worth looking into. I think the first branch can also be vectorized (e.g. with cumprod), although I haven't tried yet.
William Ambrose
William Ambrose el 6 de Oct. de 2020
You are right with respect to the true/false, I will definitly use
i = [false; A.Var1(1:end-1) == A.Var1(2:end)]
to get the logical array, I suspect it will make a big impact.

Iniciar sesión para comentar.

Respuestas (1)

Mohammad Sami
Mohammad Sami el 6 de Oct. de 2020
Something like this will work.
i = [false; A.Var1(1:end-1) == A.Var1(2:end)];
j = find(i);
A.Var3(i) = A.Var2(j) .* A.Var2(j-1);
A.Var3(~i) = A.Var2(~i);
  5 comentarios
William Ambrose
William Ambrose el 8 de Oct. de 2020
Hi Mohammed,
I like the use of grouptransform but unfortunately the use of @cumprod as the function isn't correct. What I need is an iterative cascade through the rows where the result in the previous row - in another column - is input into the calculation. Almost like a FOR LOOP solution for the Fibonnaci sequence.
To be sure I will include the corrected version of the code, with some of your suggestions embedded in, and expected outcome:
B = table([1;1;1;1;1;2;2;2;3],[1;2;3;4;5;6;7;8;500]);
B.Var3 = zeros(height(B),1);
i = [false; B.Var1(1:end-1) == B.Var1(2:end)];
j = find(~i);
B.Var3(j) = B.Var2(j);
tic;
for n = 1:height(B)
if i(n) == 1
B.Var3(n) = B.Var3(n-1) .* B.Var2(n);
end
end ; toc
and the result
B =
9×3 table
Var1 Var2 Var3
____ ____ ____
1 1 1
1 2 2
1 3 6
1 4 24
1 5 120
2 6 6
2 7 42
2 8 336
3 500 500
I have appreciate all your suggestions so far so if you have input which could solve the above but without the FOR LOOP I would be very greatful for any input.
Mohammad Sami
Mohammad Sami el 8 de Oct. de 2020
Hi William,
For the updated problem as stated, grouptransform with cumprod will work just as well.
My testing shows the result is identical to the expected result.
A =
9×3 table
Var1 Var2 fun_Var2
____ ____ ________
1 1 1
1 2 2
1 3 6
1 4 24
1 5 120
2 6 6
2 7 42
2 8 336
3 500 500
Ofcourse if the formula changes, for loop may be more generalizable.

Iniciar sesión para comentar.

Categorías

Más información sobre Performance and Memory en Help Center y File Exchange.

Productos


Versión

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by