Reputation: 107
I will use find
to get the indices from a matrix (named lag
) and then sum their corresponding values from another matrix (H
). This will require a for
loop. (The matrices are 2D.)
(max
is used here to implying a generic example)
D=zeros(max, 1)
for j = 1:max
ind = find(lag==j)
D(j) = sum(H(ind))
end
This is a 4 point example. Points are at (1,1), (1,2), (2,1), (2,2). This is part of a geostatistical method. The distance between all points has been calculated in H
. lags
is H
but rounded down and then a plus 1 to associate the distances with their closest integer (a classification called lag). I now want to sum the total distance for each lag
into vector D
.
lag
(4x4) - stores the general lag interval
1 2 2 2
2 1 2 2
2 2 1 2
2 2 2 1
H
(4x4) - stores the distance between points
0 1 1 1.414
1 0 1.414 1
1 1.414 0 1
1.414 1 1 0
Can I do this without for
loops?
Upvotes: 2
Views: 93
Reputation: 112659
This is easily done with accumarray
:
D = accumarray(lag(:), H(:));
This accumulates (sums) values of the second argument (H
linearized to a column vector) for each group defined by the values of the first argument (lag
linearized to a column vector).
Upvotes: 3
Reputation: 35080
You can do this with
ulag = unique(lag); %contains [1 2]
D = arrayfun(@(l)sum(H(lag==l)),ulag);
unique(lag)
will distil lag
into unique values, in your small example [1 2]
. Then arrayfun
will go over the array ulag
, and for each element l
it will perform sum(H(lag==l))
, which does exactly what you want: sums those elements from H
for which the corresponding element in lag
is equal to l
. Note that this only works fine if lag
contains integers, otherwise unique
might not find identical elements due to machine precision (but from your question I gathered that it is probably inherently an integer).
Also note that the above two lines could also have been written in one:
D = arrayfun(@(l)sum(H(lag==l)),unique(lag));
I just thought that after separation it might be easier to digest.
Also also note that the above makes use of that the values of lag
start from 1 up to a maximal value without gaps. If this is not the case, then you should do something like
D(unique(lag)) = arrayfun(@(l)sum(H(lag==l)),unique(lag));
but in this case you have to make sure that lag
doesn't contain non-positive values.
Upvotes: 3
Reputation: 542
There isn't a good way to do this without a for
loop, but you can do it without using find
.
D = zeros(N, 1)
for j = 1:N
D(j) = sum(sum((lag == j).*H));
end
The result of lag == j
will be a 4x4 (or rather NxN) matrix of boolean values such that (lag == j).*H
will retain the distances for each lag but have zeros for all other elements. Summing all of the elements in (lag == j).*H
will then give you the same answer for D(j)
.
Note I have switched max
to be N
since max
is a built-in MATLAB function.
Upvotes: 0