# [✓] Pick columns or rows of a matrix?

Posted 9 months ago
1180 Views
|
9 Replies
|
10 Total Likes
|
 I work with random matrices made of 0 and 1. Once generated, I want to remove the columns that contains only zero's. I can easily identify these columns (as a list), and I can remove one column at a time. How to do it in one operation ? Here is how the nb starts: m = 100; n = 10 A = RandomInteger[1, {m, n}] Position [A, Table[0, n]] ...An alternative would be to exclude from the start columns with only zero's. Thanks for suggestions. Pierre Dehez, University of Louvain, Louvain-la-Neuve
9 Replies
Sort By:
Posted 9 months ago
 You can do the detection and removal at once: m = 100; n = 4 A = RandomInteger[1, {m, n}] Count[A, {0, 0, 0, 0}] A = A /. {0..} :> Nothing Count[A, {0, 0, 0, 0}] Basically, it replaces rows that are made up of only repetitions of 0 with Nothing (if you have an older version substitute Nothing with Sequence[])
Posted 9 months ago
 Thanks! Elegant. Pierre
Posted 9 months ago
 You could also use: m = 100; n = 4 A = RandomInteger[1, {m, n}] Position[A, Table[0, n]] Delete[A, %] Delete can accept multiple 'deletions' at the same time…
Posted 9 months ago
 Even simpler, thanks! I had overlooked the Delete command.
Posted 9 months ago
 The function DeleteCases could be used. Create a matrix where 0 is twice as likely to occur as 1: In[1]:= matrix = RandomChoice[{50, 25} -> {0, 1}, {20, 3}] Out[1]= {{1, 0, 0}, {0, 0, 0}, {0, 0, 1}, {1, 1, 1}, {0, 0, 0}, {1, 0, 0}, {1, 0, 1}, {0, 0, 1}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 1, 0}, {0, 0, 1}, {0, 1, 1}, {1, 0, 0}, {1, 1, 0}, {1, 0, 0}, {0, 1, 0}} In[2]:= Length@matrix Out[2]= 20 Then DeleteCases could remove the rows that does not have at least one nonzero element: In[3]:= matrixCleanedOfAllZeroRows = DeleteCases[matrix, {0 ..}] Out[3]= {{1, 0, 0}, {0, 0, 1}, {1, 1, 1}, {1, 0, 0}, {1, 0, 1}, {0, 0,1}, {0, 1, 0}, {0, 0, 1}, {0, 1, 1}, {1, 0, 0}, {1, 1, 0}, {1, 0, 0}, {0, 1, 0}} In[4]:= Length@matrixCleanedOfAllZeroRows Out[4]= 13 
Posted 9 months ago
 Great also because you suggest a way to produce matrices with few 1's, what I needed.
Posted 9 months ago
 To sum up, there are at least a dozen ways of doing it, and you can come up with a couple dozen more if one wants… Select[A, Positive@*Total] Select[A, AnyTrue@Positive] Select[A, Not@*AllTrue[PossibleZeroQ]] A /. {0 ..} :> Nothing A /. {0 ..} :> Sequence[] Delete[A, Position[A, Table[0, n]]] Delete[A, Position[A, {0 ..}]] DeleteCases[A, {0 ..}] Cases[A, Except[{0 ..}]] Select[A, MemberQ[1]] Pick[A, Positive@*Total /@ A, True] Pick[A, NoneTrue[Positive] /@ A, False] Reap[Scan[If[MemberQ[#, 1], Sow[#]] &, A]][[2, 1]] Reap[If[MemberQ[#, 1], Sow[#]] & /@ A][[2, 1]] good luck studying them…
 One way to find which columns in a 0/1 matrix mat are zero vectors is to examine Total[mat], which gives the number of ones in each column, or Unitize[Total[mat]], which will be a 0/1 list in which a 0 means the corresponding column is all zeros.If the matrix is mostly zeros, then using SparseArray is worth considering. Here is an example with a random number of ones (5 in the example shown). nn = 10; ones = RandomInteger[{1, 2 nn}]; (* a random number of ones *) mat = SparseArray[RandomInteger[{1, nn}, {ones, 2}] -> 1, {nn, nn}]; mat // MatrixForm The following shows which columns have a one and which no ones at all: TableForm[ Unitize@Total@mat, TableHeadings -> Automatic, TableDirections -> Row ] SparseArray has a built-in method that picks the columns indices of the nonzero entries. They do not necessarily come ordered and there may be repeated indices. We can sort and remove the duplicates with Union. Compare the indices below with the positions of 1 in the table above: Union @@ mat["ColumnIndices"] (* {2, 3, 5, 9, 10} *) We can use these indices to get the columns with at least one 1 with Part and All: newmat = mat[[All, Union @@ mat["ColumnIndices"]]]; newmat // MatrixForm