4

I need to understand accumarray to write a code that I really need.

I tried to understand http://www.mathworks.co.kr/kr/help/matlab/ref/accumarray.html

Most examples were clear.

However, in the 1st example of Example 2, I thought

(1,2)th element of B should be 1

because

(1,2) = 1st, 2nd of subs
1st, 2nd of vals = 101, 102
sum(diff([101,102]))=1

Also, in the 2nd example of Example 2, I thought

(1,2)th element of B1 should be 2 instead of -2

because

(1,2) = 1st, 3rd of subs
1st, 3rd of vals = 101, 103
sum(diff([101,103]))=2

and also I thought

(4,1)th element of B1 should be 1 instead of -1

because

(4,1) = 5,6th of subs
5,6th of vals = 105,106
sum(diff([105,106]))=1

What am I missing?

Please correct, I need to understand accumarray in depth to write my own code.

user1849133
  • 527
  • 1
  • 7
  • 18

2 Answers2

2

I think the unexpected values are because you are expecting the values to be passed to the anonymous function in the same order as the relevant indices appears in subs.

However, the documentation for accumarray says:

Note If the subscripts in subs are not sorted, fun should not depend on the order of the values in its input data.

This means that the start of subs ( 1 2; 1 2; ) can result in 102 101 or 101 102 being passed to the anonymous function (because the documentation says that fun should not depend on the order of values.

sum(diff([102 101])) is -1 which is the value written to element 1,2 in the example

val = 101:106;
subs=[1 2; 1 2; 3 1; 4 1; 4 4; 4 1];
B = accumarray(subs,val,[],@(x)sum(diff(x)))

B =

     0    -1     0     0
     0     0     0     0
     0     0     0     0
     2     0     0     0

I'm not sure why Mathworks would choose to use the diff function in an example when the result of diff is obviously dependent on the order of values passed to it.

It looks like this input value ordering is the reason for the other output values being different from your expectations.

grantnz
  • 7,322
  • 1
  • 31
  • 38
  • Just noticed you've asked a very similar question before. http://stackoverflow.com/questions/17774015/matlab-accumarray-unexpectedly-changing-ordering – grantnz Nov 01 '13 at 07:43
  • Thank you. But then how can I know whether MatLab will pass [102 101] or [101 102] ? If I don't know this then obviously I can't code in a systematic way. – user1849133 Nov 01 '13 at 12:20
  • chappjc shows how to sort the subs and apply this sort order to vals to get the answer you are after. – grantnz Nov 02 '13 at 06:47
1

The why is in grantnz's answer, here's how to get predictable behavior.

As the documentation say, "If the subscripts in subs are not sorted, fun should not depend on the order of the values in its input data." So, to get predictable behavior out of accumarray, the subs have to be sorted.

What that means for subscripts representing (row,column) locations in a matrix is that the elements to which the subscripts point must be ordered according to the linear index. Thus, to "sort" 2D subscripts, you need to sort the equivalent linear index. Then you need to apply that order to vals, otherwise you have scrambled your data.

val = 101:106;
subs = [1 2; 1 2; 3 1; 4 1; 4 4; 4 1];

% convert the subscripts to linear inds and sort them
inds = sub2ind([4 4],subs(:,1),subs(:,2));
[indsSorted,sortingInds] = (sort(inds));

% apply the sorting to val
valsSorted = val(sortingInds);

% convert inds back to subs
[iiS jjS] = ind2sub([4 4],indsSorted);
subsSorted = [iiS jjS];

B = accumarray(subsSorted,valsSorted,[],@(x)sum(diff(x)))

B =

     0     1     0     0
     0     0     0     0
     0     0     0     0
     2     0     0     0

At least it would see that this is what that note in the documentation is saying.

chappjc
  • 30,359
  • 6
  • 75
  • 132