2
$\begingroup$

Is there any equivalent of MATLAB's accumarray?

I'm looking for an equivalent of:

accumarray(A(:),B(:),[],@mean)

where A and B are two matrix datasets.

EDIT: As asked in the comment, I will provide a bit more from the MATLAB code. As far as I understood, the first matrix contains a set of radius values (all integer values), the second contains a random pattern (here 0's and 1's) like this:

(* A(:) *)
a = Table[Round@Sqrt[x^2 + y^2], {y, -5, 5, 1.}, {x, -5, 5, 1}];
(* B(:) *)
SeedRandom[1238];
b = Table[x y, {y, RandomInteger[1, 5]}, {x, RandomInteger[1, 5]}] 

Now accumarray(A(:),B(:),[],@mean) seems to virtually collect all matrix elements of $b$ where the elements $a_{ij}$ share the same value and than the function @mean is applied to all those virtually collected values. After this the obtained values are written in a List containing {Value of a, mean of all values of b}. I think this is what the code is supposed to do.

$\endgroup$
15
  • $\begingroup$ Any $n \times m$ Matrix, Input as well as output. $\endgroup$
    – Kay
    Aug 17, 2017 at 12:44
  • 2
    $\begingroup$ @Kay This site is about Mathematica, information not related to it should be included or linked, that is quite obvious. Unless we talk about common knowledge, but the definition of accumarray does not seem to be part of it. $\endgroup$
    – Kuba
    Aug 17, 2017 at 13:00
  • 1
    $\begingroup$ @Kuba Thanks for your hint! I'll try to respect that for the next time! $\endgroup$
    – Kay
    Aug 17, 2017 at 13:04
  • 1
    $\begingroup$ I'm not sure I understand. All you need to do is explain what you want to do in plain English, and not rely on a piece of MATLAB. The question should be understandable even if that MATLAB code is removed. Or are you saying that you do not fully understand what accumarray(A(:),B(:),[],@mean) does? $\endgroup$
    – Szabolcs
    Aug 17, 2017 at 13:20
  • 2
    $\begingroup$ @Kay actually, I doubt that MORE matlab code would help. I was hoping you could show us a simple example of the inputs you would give to this function in Mathematica notation, and the output you desire, also in Mathematica notation, together with a description in English of the operation you want to carry out. If you don't understand what that piece of code does, you might go ask about that on a MATLAB forum first. $\endgroup$
    – MarcoB
    Aug 17, 2017 at 13:26

1 Answer 1

5
$\begingroup$
 SeedRandom[1238];
 n = 10;
 m = 100;
 f = Mean;
 a = RandomInteger[{1, n}, {m, 2}];
 b = RandomInteger[{0, 1}, {m}];

The first application of accumarray that came to my mind is the assembly of SparseArrays. This can be directly done with

sparseresult = With[{spopt = SystemOptions["SparseArrayOptions"]},
  Internal`WithLocalSettings[
   SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> f@*List}],
   SparseArray[a -> b],
   SetSystemOptions[spopt]]
  ];
sparseresult["NonzeroValues"]

A more flexible (but not as efficient way) to do it is by using GrouBy as follows

groupbyresult = Map[
  f,
  GroupBy[Transpose[{a, b}], First -> Last]
  ]

An alternative way can be obtained with Merge

mergeresult = Merge[
  Association /@ Thread[Rule[a, b]],
  f
  ]

Note that the ordering of the resulting array is not uniquely defined. Hence, using Associations is a robust way to represent it.

$\endgroup$
5
  • $\begingroup$ What is the purpose of Flatten@b in groupbyresult? b already has a flattened form?! $\endgroup$
    – Kay
    Aug 17, 2017 at 15:03
  • 1
    $\begingroup$ None. I removed it. $\endgroup$ Aug 17, 2017 at 15:06
  • 2
    $\begingroup$ For safety, one might consider using Internal`WithLocalSettings[] (see e.g. this) when playing around with SetSystemOptions[]. $\endgroup$ Aug 17, 2017 at 15:39
  • $\begingroup$ @J.M.: Thanks for the hint! I have incorporated it into the answer and also into my own utility package. $\endgroup$ Aug 18, 2017 at 1:41
  • $\begingroup$ Probably the only thing I would have done differently would be to put in sparseresult = SparseArray[a -> b]; sparseresult["NonzeroValues"] (or even SparseArray[a -> b] @ "NonzeroValues" if you like things terse) as the second argument to Internal`WithLocalSettings[]; as mentioned in the answer I linked to, whatever is in the second argument is automatically returned. But, your way works too. $\endgroup$ Aug 18, 2017 at 9:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.