4
$\begingroup$

Possibly it is duplicate, still I could not find here elegant way to remove matrix columns basing on binary sequence. i.e. if I apply {1,1,0,0,1,0,1} to matrix it should delete columns 3,4 and 6.

$\endgroup$
8
  • 5
    $\begingroup$ You can simply use matrix[[All, Pick[Range@Last@Dimensions@matrix, mask, 1]]], where matrix is your matrix, and mask is in your case {1,1,0,0,1,0,1}. $\endgroup$ Jun 27, 2016 at 18:38
  • 3
    $\begingroup$ Another option: matrix[[All, Flatten[Position[{1, 1, 0, 0, 1, 0, 1}, 1]]]] $\endgroup$
    – Coolwater
    Jun 27, 2016 at 18:52
  • 3
    $\begingroup$ Also, Pick[Transpose[matrix], {1, 1, 0, 0, 1, 0, 1}, 1] // Transpose $\endgroup$
    – Bob Hanlon
    Jun 27, 2016 at 19:20
  • 1
    $\begingroup$ Similar to @BobHanlon's: Pick[matrix, Table[{1, 1, 0, 0, 1, 0, 1}, {Length@matrix}], 1]. Or, just to be safe: Pick[matrix, Table[PadRight[{1, 1, 0, 0, 1, 0, 1}, Last@Dimensions@matrix], {Length@matrix}], 1]. $\endgroup$
    – march
    Jun 27, 2016 at 20:37
  • 1
    $\begingroup$ Also for Mathematica 10 or higher: matrix[[;; , PositionIndex[{1, 1, 0, 0, 1, 0, 1}][1]]] $\endgroup$
    – user1066
    Jun 16, 2017 at 12:32

6 Answers 6

4
$\begingroup$

Various solutions were posted in comments:

matrix = RandomInteger[10, {3, 7}];
mask = {1, 1, 0, 0, 1, 0, 1};

(* Leonid Shifrin *)
matrix[[All, Pick[Range@Last@Dimensions@matrix, mask, 1]]]

(* Coolwater *)
matrix[[All, Flatten[Position[mask, 1]]]]

(* Bob Hanlon *)
Pick[Transpose[matrix], mask, 1] // Transpose

(* march *)
Pick[matrix, Table[mask, {Length@matrix}], 1]

(* Alexey Popkov (for Mathematica 10 or higher) *)
Extract[matrix, {All, Flatten@Position[mask, 1]}]
$\endgroup$
3
$\begingroup$
list =
  {{2, 2, 1, 9, 8, 5, 6},
   {2, 5, 7, 2, 7, 3, 5},
   {0, 9, 5, 1, 9, 0, 4}};

mask = {1, 1, 0, 0, 1, 0, 1};

Pre-define p for better comparability:

p = Position[mask, 0]

{{3}, {4}, {6}}

Delete[p] /@ list

returns

{{2, 2, 8, 6},
 {2, 5, 7, 5},
 {0, 9, 9, 4}}

We get the same result with

MapAt[Nothing, p] /@ list;

ReplaceAt[_ :> Nothing, p] /@ list;

ReplacePart[p :> Nothing] /@ list;
$\endgroup$
3
$\begingroup$
list = {{2, 2, 1, 9, 8, 5, 6}, {2, 5, 7, 2, 7, 3, 5}, {0, 9, 5, 1, 9, 
    0, 4}};
mask = {1, 1, 0, 0, 1, 0, 1};

f = FoldList[If[Last@#2 == 1, First@#2, Nothing] &, Nothing, 
    Transpose[{#, mask}]] &;

f /@ list

{{2, 2, 8, 6}, {2, 5, 7, 5}, {0, 9, 9, 4}}

$\endgroup$
3
$\begingroup$
list = {{2, 2, 1, 9, 8, 5, 6}, {2, 5, 7, 2, 7, 3, 5}, {0, 9, 5, 1, 9, 0, 4}};

mask = {1, 1, 0, 0, 1, 0, 1};


list[[All, Flatten @ SparseArray[mask]["ExplicitPositions"]]]
{{2, 2, 8, 6}, {2, 5, 7, 5}, {0, 9, 9, 4}}
$\endgroup$
3
  • 1
    $\begingroup$ (+1) and happy new year! I am sure you know, but I am saying it in any case. NonzeroPositions also works $\endgroup$
    – bmf
    Jan 3 at 6:34
  • 1
    $\begingroup$ Thank you and happy new year to you too @bmf. (I recently noticed the new property names for SparseArray. Old property names still work but the documentation page uses the new names.) $\endgroup$
    – kglr
    Jan 3 at 6:42
  • $\begingroup$ All hail the old-school :-) $\endgroup$
    – bmf
    Jan 3 at 6:52
3
$\begingroup$

Another way to do this is to define the following function:

f[vec_?VectorQ, binseq_] := vec*(binseq /. (0 -> 0.))
f[mat_?MatrixQ, binseq_] := Map[f[#, binseq] &, mat] /. {0. -> Nothing}

Grabbing the @eldo's matrix:

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

mask = {1, 1, 0, 0, 1, 0, 1};

f[m1, mask]

(*{{2, 2, 8, 6}, {2, 5, 7, 5}, {0, 9, 9, 4}}*)

m2 = { {2.1, 2.2, 1.3, 9.4, 8.5, 5.6, 6.7}, 
      {2.1, 5.2, 7.3, 2.4, 7.5, 3.6, 5.7}, 
      {0.1, 9.2, 5.3, 1.4, 9.5, 0.6, 4.7} };

f[m2, mask] === m2[[All, Flatten@SparseArray[mask]["ExplicitPositions"]]]

(*True*)
$\endgroup$
1
  • 1
    $\begingroup$ It is an integers only solution. $\endgroup$
    – Syed
    Jan 3 at 5:04
2
$\begingroup$

Explanation:

Rename all elements equal to 0 in the original list to something, say x Multiply each sublist by the mask Keep only the elements that are not equal to 0 Rename x to 0 which are the ones from the list and not the mask

This is a prime candidate for Threaded

With

list = {{2, 2, 1, 9, 8, 5, 6}, {2, 5, 7, 2, 7, 3, 5}, {0, 9, 5, 1, 9, 
    0, 4}};
mask = {1, 1, 0, 0, 1, 0, 1};

we do

DeleteCases[(list //. 0 -> x) Threaded[mask], 0, Infinity] /. x -> 0

to get

{{2, 2, 8, 6}, {2, 5, 7, 5}, {0, 9, 9, 4}}

$\endgroup$
1
  • 1
    $\begingroup$ (+1) Nicely done, mate! :-) $\endgroup$ Jan 3 at 13:15

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.