8
$\begingroup$

Inspired by this question from @sjdh and by my recurrent use of columns operations in database sets, I was looking for one way to make columns operations more symetric, so I can handle with matrix and lists in a more clean way when working with this kind of data.

For instance, I think it's not very practical to append a list data to a matrix using Join[matA, {colA} // Transpose, 2] or prepend using Prepend[Transpose@matA, colA] // Transpose. It's very clumsy, but we get used to it (I realized that teaching to a friend).

I created this function called colAppend, that I would like to share here, and ask for performance tuning, tips on code organization and maybe another combinations of row operations that I have missed.

Here are our test matrix and lists:

matA={{mA1,mA2},{mA3,mA4},{mA5,mA6}};
matB={{mB1,mB2},{mB3,mB4},{mB5,mB6}};
colA={cA1,cA2,cA3};
colB={cB1,cB2,cB3};

Now there are the function colAppend definitions. I separated it in 3 blocks:

1- Basic Join Operations

colAppend[mat1_,mat2_]/;(Length@Dimensions@mat1>1&&Length@Dimensions@mat2>1):=
    Join[mat1,mat2,2]

colAppend[mat1_,col1_,pos_:-1]/;(Length@Dimensions@mat1>1&&Length@Dimensions@col1==1):=
    Insert[mat1//Transpose, col1, pos]//Transpose

colAppend[col1_,col2_]/;(Length@Dimensions@col1==1&&Length@Dimensions@col2==1):=
    Transpose[{col1,col2}]

colAppend[col1_,mat1_,pos_:1]/;(Length@Dimensions@col1==1&&Length@Dimensions@mat1>1):=
    Insert[mat1//Transpose, col1, pos]//Transpose

colAppend[colA,matA]//MatrixForm
colAppend[colA,colB]//MatrixForm
colAppend[matA,matB]//MatrixForm
colAppend[matA,colA]//MatrixForm

enter image description here

2- Deleting Columns

Maybe it could be another function colDelete, so we could remove the Null parameter.

colAppend[mat1_,Null,pos_:-1]/;(Length@Dimensions@mat1>1):=
Module[{temp=mat1},
    temp[[All,pos]]=Sequence[];
    temp
]

colAppend[Null,mat1_,pos_:1]/;(Length@Dimensions@mat1>1):=
Module[{temp=mat1},
    temp[[All,pos]]=Sequence[];
    temp
]

colAppend[matA,Null]//MatrixForm
colAppend[Null,matA]//MatrixForm

enter image description here

3- Join Multiple Elements

Combine all the above function (with except Null one)

colAppend::badargs = "Incompatible Dimensions";
colAppend[args__]:=Module[{list=List[args]},
    If[\[Not]Equal@@(First@Dimensions@#&/@list),Return[Message[colAppend::badargs]]];
    Fold[colAppend,First@list,Rest@list]
]

MatrixForm@colAppend[matA,colA,matB,colB]

enter image description here

What another functionality I'm missing?

What is the best way to create such function?

Update 1

As VLC has posted in the comments. For part 3, this answer from @Mr.Wizard is the best option, not just in simplicity, but in performance too!

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

2 Answers 2

2
$\begingroup$

After some time looking for how to handler that question, I get into this set of function, that I have added to my tool-bag. The first one (colAttach) is from @Mr.Wizard.

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

colInsert[mat1_?MatrixQ,col1_?VectorQ,pos_:-1]:=Insert[mat1//Transpose, col1, pos]//Transpose
colInsert[mat1_?MatrixQ,mat2_?MatrixQ,pos_:-1]:=Insert[mat1//Transpose, mat2, pos]//Transpose//Flatten[#,1]&/@#&

colDelete[mat1_?MatrixQ,pos_:-1]:=Module[{r},
    r=mat1;
    r[[All,pos]]=Sequence[];
    r
]

colPermute[mat_List?MatrixQ,permCicle_List]:=Module[{r=mat,permute},
    Scan[(r[[All,#]]=r[[All,Reverse@#]])&,If[VectorQ[permCicle],{permCicle},permCicle]];
    r
]

The use of the first 3 (colAttach, colInsert and colDelete) works just as stated in the question.

The last one (colPermute) use the structure.

matA = {{mA1, mA2, mA3}, {mA1, mA2, mA3}, {mA1, mA2, mA3}};
mrtColPermute[matA, {1, 2}] // MatrixForm
mrtColPermute[matA, {{1, 2}, {3, 1}}] // MatrixForm

permuted matrix

$\endgroup$
1
$\begingroup$

As already noted the column append part of this question is answered here.

colDelete is already implemented as Drop, though you could tweak the syntax if you desire:

a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

Drop[a, None, {2}]
{{1, 3}, {4, 6}, {7, 9}}

Insert was asked about on StackOverflow: How to insert a column into a matrix, the correct Mathematica way

The double Transpose was the best method found.

$\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.