11
$\begingroup$

I have an $M \times K$ matrix $C$ and a length $K$ vector $v$. I want to form the $M \times K$ matrix $S$ where $s_{ij} = C_{ij}/v_j$. To do this in numpy I simply divide the two objects like this

  S = C/v

but that fails in Mathematica.

What is the most efficient way to do this?

$\endgroup$
5
  • $\begingroup$ S=#/v & @@@ C; Best regards to Mr.Wizard! $\endgroup$
    – faleichik
    Mar 11, 2012 at 20:09
  • 4
    $\begingroup$ @faleichik Shouldn't that be #/v & /@ C? $\endgroup$
    – Heike
    Mar 11, 2012 at 20:33
  • 5
    $\begingroup$ One important thing to keep in mind when you're coming from MATLAB is that arrays in Mathematica are general $n$-dimensional tensors, while MATLAB works with matrices only. This has a significant influence on how operations work in the two systems. In Mathematica there is no such thing as a row vector and columns vector: a vector is a strictly 1D structure and both the product vec.mat and mat.vec work. (You can of course have an $1\times n$ or $n\times 1$ matrix.) Operations between $m \times k$ matrices and $m$-length vectors do work automatically, but not with $k$-length vectors. $\endgroup$
    – Szabolcs
    Mar 11, 2012 at 20:40
  • 4
    $\begingroup$ Another advice: don't use identifiers with capital names in Mathematica to avoid conflicts with builtins and packages. Both C and K are built-in symbols, and assigning to either of them will break the system in subtle ways (for those who wonder, yes: even assigning to K breaks it, I have seen examples). $\endgroup$
    – Szabolcs
    Mar 11, 2012 at 20:41
  • $\begingroup$ @Heike yes, it definitely should. I promise to never post anything without verifying it. $\endgroup$
    – faleichik
    Mar 12, 2012 at 4:19

4 Answers 4

16
$\begingroup$

The problem is that Mathematica wants to match up $v$ with the rows of $C$. In order to get what you want, you can do:

S=Transpose[Transpose[C]/v]
$\endgroup$
2
  • $\begingroup$ Here's what it should look like :Mathematica graphics $\endgroup$
    – CHM
    Mar 11, 2012 at 20:53
  • $\begingroup$ Perfect, thank you! $\endgroup$
    – Brian B
    Mar 12, 2012 at 2:06
13
$\begingroup$

I'll construct a $5\times3$ matrix of ones to use for illustration purposes:

m = ConstantArray[1,{5, 3}]

enter image description here

We can multiply each row by the corresponding element from a vector using simple multiplication:

m*{1,2,3,4,5}

enter image description here

Multiplying each column by the corresponding element from a vector is a bit more complicated. There are several possibilities, some of which are already covered by others, but here's one I like for being conceptually simple in that it doesn't use Transpose or explicit iteration (Table, Map, etc...)

ScalingTransform[{1,2,3}][m]

enter image description here

This could also be written using postfix notation m // ScalingTransform[{1,2,3}] if desired.


After looking at Artes's timing comparison, the ScalingTransform approach is quite slow, since it's constructing a large dense matrix. We can use the same underlying idea using a specially constructed SparseArray, however, which is much faster:

m.SparseArray[Band[{1, 1}] -> {1,2,3,4,5}]

Cc = RandomReal[{100}, {700, 900}];
v = RandomReal[{100}, {900}];

ScalingTransform[1/v][Cc]; // AbsoluteTiming

(* ==> {16.333062, Null} *)

Cc.SparseArray[Band[{1, 1}] -> 1/v]; // AbsoluteTiming

(* ==> {0.021044, Null} *)
$\endgroup$
3
  • 2
    $\begingroup$ One thing I always wondered: In Mathematica, is Transpose an $O(1)$ operation or is it proportional to the number of elements? (Does it actually copy stuff in memory or does it just flip a switch on how to interpret the in-memory data?) $\endgroup$
    – Szabolcs
    Mar 11, 2012 at 20:43
  • 3
    $\begingroup$ @Szabolcs I believe Transpose actually copies stuff in memory, which is backed up by looking at how long it takes to transpose matrices of various (large-ish) sizes. $\endgroup$ Mar 11, 2012 at 20:54
  • $\begingroup$ DiagonalMatrix[1/v, SparseArray] will work as well. $\endgroup$ Oct 14, 2018 at 7:20
10
$\begingroup$

Not the most efficient way but sufficiently instructive can be for example this:

Cc = RandomInteger[{1, 10}, {3, 4}]
v = RandomInteger[{1, 10}, {4}]
S = Table[Cc[[i, j]]/v[[j]], {i, 1, 3}, {j, 1, 4}]
  {{7, 9, 6, 4}, {2, 3, 5, 8}, {6, 1, 7, 4}} 
  {2, 2, 4, 3}
  {{7/2, 9/2, 3/2, 4/3}, {1, 3/2, 5/4, 8/3}, {3, 1/2, 7/4, 4/3}} 

This hasn't been mentioned, it's nice but not very efficient :

Inner[Divide, Cc, v, List]

Let's compare performances of various methods :

Cc = RandomReal[{100}, {700, 900}];
v  = RandomReal[{100}, {900}];

S1 = Table[ Cc[[i, j]] / v[[j]], {i, 1, 700}, {j, 1, 900}]; // AbsoluteTiming
S2 = Inner[Divide, Cc, v, List]; // AbsoluteTiming
S3 = #/v & /@ Cc; // AbsoluteTiming
S4 = Transpose[Transpose[Cc]/v]; // AbsoluteTiming
{0.1080000, Null} 
{0.4310000, Null}
{0.0180000, Null} 
{0.0260000, Null}
S1 == S2 == S3 == S4
True

It appears the method based on Map is the best with respect to performance issues.

$\endgroup$
1
  • $\begingroup$ @Mr.Wizard Thank You ! I should add that Inner[ Times, Cc, 1/v, List] is a bit more efficient that Inner[Divide, Cc, v, List]. $\endgroup$
    – Artes
    Mar 12, 2012 at 10:02
6
$\begingroup$

You can get results roughly equally fast to sblom's double-Transpose approach using the generalised version of Inner.

Inner[Divide, matrix, vector, List]

Timing tests
Set up some example data:

ci = RandomInteger[{0, 100}, {20, 3}];
cr = RandomReal[{0., 100.}, {20, 3}];
vi = {3, 2, 1};
vr = {3., 2., 1.};

Division

In[38]:= Do[Transpose[Transpose[ci]/vi];, {1000}] // Timing (*sblom*)

Out[38]= {0.047, Null}

In[39]:= Do[#/vi & /@ ci;, {1000}] // Timing (* faleichik/Heike in comments*)

Out[39]= {0.172, Null}

In[56]:= Do[Inner[Divide, ci, vi, List];, {1000}] // Timing (* me *)

Out[56]= {0.047, Null}

In[40]:= Do[ScalingTransform[1/vi][ci];, {1000}] // Timing (* Brett *)

Out[40]= {0.39, Null}

(* as before but for real numbers *)

In[41]:= Do[Transpose[Transpose[cr]/vr];, {1000}] // Timing  

Out[41]= {0.016, Null}

In[42]:= Do[#/vr & /@ cr;, {1000}] // Timing

Out[42]= {0.109, Null}

In[57]:= Do[Inner[Divide, cr, vr, List];, {1000}] // Timing

Out[57]= {0.031, Null}

In[43]:= Do[ScalingTransform[1/vr][cr];, {1000}] // Timing

Out[43]= {0.36, Null}

Multiplication
As an aside, because of the way Divide works internally, if you are dividing through by the same vector a lot, it makes some sense to create a vector that is 1./thefirstvector and multiply through with that. The effect is more noticeable if you have integer data.

ivi = 1/vi;
ivr = 1./vr;


In[82]:= Do[Transpose[Transpose[ci]*ivi];, {1000}] // Timing 
Out[82]= {0.031, Null}

In[83]:= Do[#*ivi & /@ ci;, {1000}] // Timing
Out[83]= {0.125, Null}

In[84]:= Do[Inner[Times, ci, ivi, List];, {1000}] // Timing

Out[84]= {0.031, Null}


In[85]:= Do[ScalingTransform[ivi][ci];, {1000}] // Timing

Out[85]= {0.375, Null}

In[86]:= Do[Transpose[Transpose[cr]*ivr];, {1000}] // Timing

Out[86]= {0.016, Null}

In[87]:= Do[#*ivr & /@ cr;, {1000}] // Timing

Out[87]= {0.063, Null}

In[88]:= Do[Inner[Times, cr, ivr, List];, {1000}] // Timing

Out[88]= {0.031, Null}


In[89]:= Do[ScalingTransform[ivr][cr];, {1000}] // Timing

Out[89]= {0.343, Null}
$\endgroup$
1

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.