6
$\begingroup$

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:

output

$\endgroup$
  • 4
    $\begingroup$ Please add a code sample not a latex version. And try Transpose /@ (SplitBy[m\[Transpose], MatchQ[#, {0 ..}] &] /. {{0 ..} ..} -> Sequence[]) $\endgroup$ – Kuba Aug 20 '14 at 8:01
  • 1
    $\begingroup$ @Kuba Nice to see you post something again! $\endgroup$ – C. E. Aug 20 '14 at 9:54
  • 1
    $\begingroup$ @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 :/ $\endgroup$ – Kuba Aug 20 '14 at 20:44
4
$\begingroup$

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

Mathematica graphics

| improve this answer | |
$\endgroup$
3
$\begingroup$

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

output

| improve this answer | |
$\endgroup$
3
$\begingroup$

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.

| improve this answer | |
$\endgroup$
0
$\begingroup$

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 == # &]

A "mask" for your input:

v = Unitize @ Total @ Unitize @ mat
{1, 1, 0, 1, 0, 1}

Applied:

MatrixForm /@ splitColsByMask[mat, v]

enter image description here

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

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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