Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Having the need to attach a column to a matrix or to join matrices to make longer rows is an operation that I use very frequently and I find the Join function ideal for these cases.

m1 = {{10, 11, 12}, {21, 22, 23}};
m2 = {100, 101};

(* Join matrices to make longer rows: *)
Join[m1, m1, 2]
(* --> {{10, 11, 12, 10, 11, 12}, {21, 22, 23, 21, 22, 23}} *)

(* Attach a column to a matrix *)
Join[m1, List /@ m2, 2]
(* --> {{10, 11, 12, 100}, {21, 22, 23, 101}} *)

(* Join two columns to make a matrix *)
Join[List /@ m2, List /@ m2, 2]
(* --> {{100, 100}, {101, 101}} *)

However, I wanted to define my own function that would simplify the notation needed to reach my goal:

columnAttach[a1_List, a2_List] := 
  Join[If[VectorQ[a1], List /@ a1, a1], 
  If[VectorQ[a2], List /@ a2, a2], 2]

columnAttach[m1, m1]
(* --> {{10, 11, 12, 10, 11, 12}, {21, 22, 23, 21, 22, 23}} *)
columnAttach[m1, m2]
(* --> {{10, 11, 12, 100}, {21, 22, 23, 101}} *)
columnAttach[m2, m2]
(* --> {{100, 100}, {101, 101}} *)

This works as expected, but I would like to generalize it a bit. For instance, Join can take a list of vectors/matrices of any length:

Join[m1, m1, List /@ m2, List /@ m2, 2]
(* --> {{10, 11, 12, 10, 11, 12, 100, 100},
  {21, 22, 23, 21, 22, 23, 101, 101}} *)

How can I adapt my columnAttach function to achieve the same flexibility?

share|improve this question
1  
Why not using ArrayFlatten ? –  b.gatessucks Nov 13 '12 at 10:10
    
Related (possible dupe): mathematica.stackexchange.com/questions/189/… –  rm -rf Nov 13 '12 at 15:08
add comment

2 Answers 2

up vote 6 down vote accepted

One possibility:

columnAttach[ak__List] := Join[##, 2] & @@ Replace[{ak}, v_?VectorQ :> List /@ v, 1]

columnAttach[{{10, 11, 12}, {21, 22, 23}}, {100, 101}, {{10, 11, 12}, {21, 22, 23}},
             {100, 101}, {100, 101}]
   {{10, 11, 12, 100, 10, 11, 12, 100, 100},
    {21, 22, 23, 101, 21, 22, 23, 101, 101}}

Alternatively:

columnAttach[ak__List] := ArrayFlatten[{Replace[{ak}, v_?VectorQ :> List /@ v, 1]}]
share|improve this answer
    
..or, as the Wizard reminds, you could use the replacement rule v_?VectorQ :> Transpose[{v}]. –  J. M. Nov 13 '12 at 15:20
add comment

This appears to be faster than J. M.'s funcions in all cases on my system:

columnAttach2[ak__List] := 
  Replace[Unevaluated@Join[ak, 2], v_?VectorQ :> {v}\[Transpose], 1]

Timings, using J. M.'s Join function (which tested faster):

SetAttributes[timeAvg, HoldFirst]

timeAvg[func_] := 
  Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0, 15}]

m1 = RandomInteger[999, {50, 100}];
m2 = RandomInteger[999, 50];

columnAttach[m1, m2, m2, m1, m2, m1] // timeAvg

columnAttach2[m1, m2, m2, m1, m2, m1] // timeAvg

0.00019968

0.0000141696

share|improve this answer
    
Correction: it is no faster but also no slower than J. M.'s code for non-packed arrays but apparently always faster with packed arrays. –  Mr.Wizard Nov 13 '12 at 15:28
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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