45
$\begingroup$

Say I have a matrix m and a vector v.

v = {a[1], a[2], a[3], a[4]};

m={{a[1,1],a[1,2],a[1,3],a[1,4]},
   {a[2,1],a[2,2],a[2,3],a[2,4]},
   {a[3,1],a[3,2],a[3,3],a[3,4]},
   {a[4,1],a[4,2],a[4,3],a[4,4]}};

What is the most efficient way to add v to the rows of m to create...

mrow={{a[1],a[2],a[3],a[4]},
      {a[1,1],a[1,2],a[1,3],a[1,4]},
      {a[2,1],a[2,2],a[2,3],a[2,4]},
      {a[3,1],a[3,2],a[3,3],a[3,4]},
      {a[4,1],a[4,2],a[4,3],a[4,4]}}

Likewise, what is the most efficient way to add v to the columns of m to create...

mcol={{a[1],a[1,1],a[1,2],a[1,3],a[1,4]},
      {a[2],a[2,1],a[2,2],a[2,3],a[2,4]},
      {a[3],a[3,1],a[3,2],a[3,3],a[3,4]},
      {a[4],a[4,1],a[4,2],a[4,3],a[4,4]}};

EDIT: I've tested some of the suggestions for adding a column with a large matrix and was somewhat surprised by the results.

m = RandomVariate[NormalDistribution[], {1000, 1000}];

v = RandomVariate[NormalDistribution[], 1000];

In[37]:= AbsoluteTiming[Do[MapThread[Prepend, {m, v}], {100}];]

Out[37]= {1.809623, Null}

In[38]:= AbsoluteTiming[Do[Transpose[Prepend[Transpose[m], v]], {100}];]

Out[38]= {2.449231, Null}

In[39]:= AbsoluteTiming[Do[Transpose[Join[Transpose[m], {v}]], {100}];]

Out[39]= {2.271853, Null}
$\endgroup$
0

5 Answers 5

25
$\begingroup$

ArrayFlatten is much faster than combination of Join and Transpose:

m = RandomVariate[NormalDistribution[], {1000, 1000}];
v = RandomVariate[NormalDistribution[], 1000];

Check that ArrayFlatten gives the same output:

(* In[54]:=*) ArrayFlatten[{{Transpose[{v}], m}}] == 
 Transpose[Join[{v}, Transpose[m]]]

(* Out[54]= True *)

(* In[57]:= *) ArrayFlatten[{{Transpose[{v}], m}}] == 
 MapThread[Prepend, {m, v}]

(* Out[57]= True *)

See the timing:

(* In[55]:= *) Do[
  ArrayFlatten[{{Transpose[{v}], m}}], {10^3}] // AbsoluteTiming

(* Out[55]= {4.330433, Null} *)

(* In[58]:= *) Do[MapThread[Prepend, {m, v}], {10^3}] // AbsoluteTiming

(* Out[58]= {11.766177, Null} *)

(* In[56]:= *) Do[
  Transpose[Join[{v}, Transpose[m]]], {10^3}] // AbsoluteTiming

(* Out[56]= {16.700670, Null} *)
$\endgroup$
3
  • 3
    $\begingroup$ Join is faster than ArrayFlatten (for these examples anyway). $\endgroup$ Commented Jan 18, 2012 at 22:54
  • $\begingroup$ @MikeHoneychurch Thanks for reminding me of Join (+1). In my timings, there is no measurable difference, but I agree Join feels more natural than ArrayFlatten. $\endgroup$
    – Sasha
    Commented Jan 19, 2012 at 5:12
  • $\begingroup$ @Sasha The above timings are correct for the addition of a column to a matrix (I confirmed them), but in the case of a row, I am getting rather different results: AbsoluteTiming[Do[Join[m, {v}], {10^3}]] Out[231]={0.619549, Null} AbsoluteTiming[Do[Transpose[MapThread[Append, {Transpose[m], v}]], {10^3}]] Out[233]={8.1198, Null} AbsoluteTiming[Do[ArrayFlatten[{{m}, {{v}}}], {10^3}]] Out[232]={49.0553, Null} I think this might be useful for new users who might just copy the code, as they are still not aware what is quick/slow when it comes to working with Lists $\endgroup$ Commented Apr 4, 2017 at 9:30
34
$\begingroup$

I would (and do) use Join to add both columns and rows:

Join[{v}, m] // MatrixForm
Join[List /@ v, m, 2] // MatrixForm

enter image description here

On my system -- 8.0.4 Mac 10.6.8 -- Join is faster than ArrayFlatten, although there is not a great deal in it:

m = RandomVariate[NormalDistribution[], {1000, 1000}];
v = RandomVariate[NormalDistribution[], 1000];

Do[tmp1 = ArrayFlatten[{{Transpose[{v}], m}}], {100}]; // AbsoluteTiming
Do[tmp2 = Join[List /@ v, m, 2], {100}]; // AbsoluteTiming
Do[tmp3 = Join[Transpose[{v}], m, 2], {100}]; // AbsoluteTiming
Do[tmp4 = Join[Partition[v, 1], m, 2], {100}]; // AbsoluteTiming

{1.614537, Null}
{1.538143, Null}
{1.523499, Null}
{1.519206, Null}

tmp1 == tmp2 == tmp3 == tmp4
True
$\endgroup$
8
$\begingroup$

To add a column c to a matrix m: Transpose[Join[Transpose[m], {c}]]

To add a row r to a matrix m: Join[m, {r}]

where c and r are just lists of the new elements.

$\endgroup$
8
$\begingroup$

For mcol you could use MapThread, which I would think would be better than transposing twice. So the following gives you what you want.

mcol = MapThread[Prepend, {m, v}]
$\endgroup$
0
2
$\begingroup$

The obvious (if not most efficient) approach is Prepend: Prepend[m\[Transpose], v]\[Transpose] gives mcol while Prepend[m, v] gives mrow.

You could also obtain mrow using {v}~Join~m and mcol using ({v}~Join~m)\[Transpose]. These, though, are slower (for the specific matrices you gave).

Also

Insert[m, v, 1]

and

Insert[m\[Transpose], v, 1]\[Transpose]
$\endgroup$

Your Answer

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

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