What is the most efficient way to add rows and columns to a matrix?

41

28

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}

Andy Ross

Posted 2012-01-18T18:37:24.330

Reputation: 18 640

Answers

23

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} *)

Sasha

Posted 2012-01-18T18:37:24.330

Reputation: 7 203

@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 – ThunderBiggi – 2017-04-04T09:30:22.193

3Join is faster than ArrayFlatten (for these examples anyway). – Mike Honeychurch – 2012-01-18T22:54:08.123

@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. – Sasha – 2012-01-19T05:12:30.490

29

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

Mike Honeychurch

Posted 2012-01-18T18:37:24.330

Reputation: 36 211

6

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}]

Adam Berry

Posted 2012-01-18T18:37:24.330

Reputation: 304

6

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.

uli

Posted 2012-01-18T18:37:24.330

Reputation: 1 275

2

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]

acl

Posted 2012-01-18T18:37:24.330

Reputation: 19 146