1
$\begingroup$

Lets say that I have a Table of dimension (3,3,500) and I'd like to perform element-wise division by a 3x3 matrix along the third dimension (of length 500 in this case).

What is the most elegant way of vectorizing this operation?

$\endgroup$
  • 2
    $\begingroup$ why not simply use Divide; e.g. mata = RandomInteger[10, {3, 3, 500}]; matb = ArrayReshape[CharacterRange["a", "z"][[;; 9]], {3, 3}]; mata/matb? $\endgroup$ – kglr May 6 '15 at 18:40
  • $\begingroup$ This is true! Sorry, coming from the MATLAB world where no inference is made about what you're doing and matrix dimensions have to match for element-wise operations. $\endgroup$ – PatternMatching May 7 '15 at 13:59
3
$\begingroup$

You can do this in a few ways, but the most elegant is to use the method in kguler's comment on your original post, which is just to divide:

M = RandomReal[{-1, 1}, {3, 3, 500}];
div = RandomReal[{-1, 1}, {3, 3}];
result = M / div;

Because the Divide (/) function has the Listable attribute, it automatically threads over the outer level of its arguments in the case that they are lists; accordingly, M / div effectively becomes:

{M[[1]]/div[[1]], M[[2]]/div[[2]], M[[3]]/div[[3]]}

Because each of these are also lists, however, this gets further threaded into:

{{M[[1,1]]/div[[1,1]], M[[1,2]]/div[[1,2]], M[[1,3]]/div[[1,3]]},
 {M[[2,1]]/div[[2,1]], M[[2,2]]/div[[2,2]], M[[2,3]]/div[[2,3]]},
 {M[[3,1]]/div[[3,1]], M[[3,2]]/div[[3,2]], M[[3,3]]/div[[3,3]]}}

which is precisely what you want. If your array M were instead a 500x3x3 matrix, you could do something like this:

M = RandomReal[{-1, 1}, {500, 3, 3}];
div = RandomReal[{-1, 1}, {3, 3}];
(* Use ConstantArray[] *)
result = M / ConstantArray[div, 500];
(* Use Transpose[] *)
result = Transpose[Transpose[M, {3,1,2}] / div, {2,3,1}];
(* Use Map[] *)
result = (#/div)& /@ M;

In the latter case, my personal preference is to use ConstantArray[], which, in my own tests, was the fastest as well (they are listed in order of their AbsoluteTimings).

$\endgroup$
  • $\begingroup$ As kguler commented, why not just use M/div ? $\endgroup$ – Simon Woods May 6 '15 at 18:51
  • $\begingroup$ kguler's comment wasn't posted when I started my response; I'm actually surprised that it works. My recollection in prior versions of Mathematica was that mismatched division explicitly failed; e.g., {{1,2},{3,4},{5,6}} / {1,2,3} would not work. I just tested it in 10.1, however, and it seemed to work. Does anyone know if this has changed or if I'm just misremembering? $\endgroup$ – nben May 6 '15 at 18:56
  • 2
    $\begingroup$ You have misremembered - automatic Listable threading works on the outermost dimension. In your example both lists are length 3 so it threads in all Mathematica versions. $\endgroup$ – Simon Woods May 6 '15 at 19:05
  • $\begingroup$ Thanks, yeah, this is pretty obvious now that I think about it. I've updated my answer to reflect the correction. $\endgroup$ – nben May 6 '15 at 20:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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