Split matrix by all-zero columns

Below is my input:

mat = {{0, 0, 0, 0, 0, 1}, {1, 0, 0, 1, 0, 1}, {0, 1, 0, 0, 0, 0}, {0,
0, 0, 0, 0, 1}, {1, 1, 0, 1, 0, 0}, {0, 0, 0, 1, 0, 1}};


$\quad\quad\left( \begin{array}{cccccc} 0 & 0 & 0 & 0 & 0 & 1 \\ 1 & 0 & 0 & 1 & 0 & 1 \\ 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 \\ 1 & 1 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 & 1 \\ \end{array} \right)$

I would like to split this matrix by the columns with all-zeros, and in the process remove those columns from the matrix. Expected output below:

• Please add a code sample not a latex version. And try Transpose /@ (SplitBy[m\[Transpose], MatchQ[#, {0 ..}] &] /. {{0 ..} ..} -> Sequence[]) – Kuba Aug 20 '14 at 8:01
• @Kuba Nice to see you post something again! – C. E. Aug 20 '14 at 9:54
• @Pickett Thanks :) that's nice of you, I will try to fully come back around october. I have a lot of boring stuff to do know :/ – Kuba Aug 20 '14 at 20:44

I'm surprised MMA doesn't have something like StringSplit for list, but maybe I haven't looked hard enough. I added the .. to delete multiple all-zero columns after seeing @Kuba's comment. Please upvote his comment instead of my answer since his was the more succinct.

mat = {{0, 0, 0, 0, 0, 1}, {1, 0, 0, 1, 0, 1}, {0, 1, 0, 0, 0, 0}, {0,
0, 0, 0, 0, 1}, {1, 1, 0, 1, 0, 0}, {0, 0, 0, 1, 0, 1}};

MatrixForm@Transpose@# & /@
DeleteCases[SplitBy[Transpose@mat, # != {0, 0, 0, 0, 0, 0} &], {{0, 0, 0, 0, 0, 0}..}]


Basically, the same idea as seismatica's answer, but with different details.

m =
{{0, 0, 0, 0, 0, 1},
{1, 0, 0, 1, 0, 1},
{0, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 1},
{1, 1, 0, 1, 0, 0},
{0, 0, 0, 1, 0, 1}};

split =
Transpose /@
DeleteCases[
SplitBy[If[Plus @@ # > 0, #] & /@ Transpose[m], # === Null &],
{Null}];


A different approach using Reap and Sow.

split =
Module[{tag = 1},
Transpose /@ Last @ Reap[If[Plus @@ # > 0, Sow[#, tag], tag++] & /@ Transpose[m]]]


Both of the above produce

MatrixForm /@ split


In the spirit of Mathematica 10 I would have written it like this:

Composition[
DeleteCases[{{0} ..}],
Map[Transpose],
SplitBy[#, Unitize@*Total] &,
Transpose
]@mat


{{{0, 0}, {1, 0}, {0, 1}, {0, 0}, {1, 1}, {0, 0}}, {{0}, {1}, {0}, {0}, {1}, {1}}, {{1}, {1}, {0}, {1}, {0}, {1}}}

With rules I would write:

Transpose /@ {Transpose[mat] //. {el__, {0 ..}, rest___} :> Sequence[{el}, {rest}]}


{{{0, 0}, {1, 0}, {0, 1}, {0, 0}, {1, 1}, {0, 0}}, {{0}, {1}, {0}, {0}, {1}, {1}}, {{1}, {1}, {0}, {1}, {0}, {1}}}

The first method assumes numeric matrix elements but the second doesn't.

Here is a function hopefully with some amount of reusability:

splitColsByMask[base_, mask_, key_: 1] :=
base[[All, #]] & /@ Split[Pick[Range@Length@mask, mask, key], #2 - 1 == # &]


v = Unitize @ Total @ Unitize @ mat

{1, 1, 0, 1, 0, 1}

MatrixForm /@ splitColsByMask[mat, v]

The third parameter "key" defaults to 1; it is the "take" pattern for Part.