From: Juliette Salexa on
Hello,

I'm trying to do the following summation without a for loop:

I have one array which looks smthg like:
f=[1 1 1 ;
1 1 3 ;
1 4 4 ;
2 1 1 ;
2 1 4 ;
2 4 4 ]

And another array:
A=rand(size(f,1),1);

And I want to add all rows of A such that the last two values in the corresponding rows of f are the same, and store these in a new array.

For the above example, I want the array S, where:

S(1)=A(1) + A(4) % since f(1,2:3)=f(4,2:3)
S(2)=A(2) % no summation since there are no rows of f such that f(i,2:3) = f(2,2:3)
S(3)=A(3) + A(6) % since f(3,2:3)=f(6,2:3)
S(4)=A(5) % since A(4) was already used,

Is this, or anything similar, possible using just array indexing rather than a for loop ?

Any help comments or discussion would be greatly appreciated!
From: Bruno Luong on
Not sure what the first column of f is for?

[U I J]=unique(f(:,2:3),'rows');
S=accumarray(J,A(:));
S=S(J)

% Bruno
From: us on
"Juliette Salexa" <juliette.physicist(a)gmail.com> wrote in message <hrklcj$7ri$1(a)fred.mathworks.com>...
> Hello,
>
> I'm trying to do the following summation without a for loop:
>
> I have one array which looks smthg like:
> f=[1 1 1 ;
> 1 1 3 ;
> 1 4 4 ;
> 2 1 1 ;
> 2 1 4 ;
> 2 4 4 ]
>
> And another array:
> A=rand(size(f,1),1);
>
> And I want to add all rows of A such that the last two values in the corresponding rows of f are the same, and store these in a new array.
>
> For the above example, I want the array S, where:
>
> S(1)=A(1) + A(4) % since f(1,2:3)=f(4,2:3)
> S(2)=A(2) % no summation since there are no rows of f such that f(i,2:3) = f(2,2:3)
> S(3)=A(3) + A(6) % since f(3,2:3)=f(6,2:3)
> S(4)=A(5) % since A(4) was already used,
>
> Is this, or anything similar, possible using just array indexing rather than a for loop ?
>
> Any help comments or discussion would be greatly appreciated!

one of the many solutions

% the data
f=[
1 1 1
1 1 3
1 4 4
2 1 1
2 1 4
2 4 4
];
v=(1:size(f,1)).'; % <- to better check results - use your vec...
% the engine
[fx,fx,fx]=unique(f(:,2:3),'rows');
r=arrayfun(@(x) sum(v(fx==x)),1:max(fx));
% the result
disp([fx,v]);
%{
1 1
2 2
4 3
1 4
3 5
4 6
%}
disp([1:max(fx);r]);
%{
1 2 3 4 % <- indices...
5 2 5 9 % <- result...
%}

us
From: Bruno Luong on

> [U I J]=unique(f(:,2:3),'rows');
> S=accumarray(J,A(:));

I think what you want is actually there, no need for the assignment
S=S(J).

Bruno
From: Juliette Salexa on
Thanks Bruno and Us!

Those are both neat and clever methods,

But the last two elements are in the wrong order (in both methods!)

The reason why my example was in this order:

S(1)=A(1) + A(4)
S(2)=A(2)
S(3)=A(3) + A(6)
S(4)=A(5)

was because I want matlab to:
(1) read the rows of f in order from top to bottom.
(2) if the row's last two entries are duplicated in some other row, add the corresponding rows of A and put the answer into S, in the first possible row that isn't occupied.
(3) if the row's last two entries are not duplicated in some other row, just put the corresponding row of A into S, in the first possible row that isn't occupied.

So in the above example, f(3,2:3)=f(6,2:3) , so I want S(3)=A(3)+A(6);

But the algorithm is making S(3)=A(5), and S(4)=A(3)+A(6),

Maybe this has something to do with UNIQUE() arranging the input elements in increasing order ?