What is the best way to remove empty rows and columns of an asymmetric square matrix if and only if they are both empty for a given index. That is, it should remove row AND column i if and only if both row i AND column i are all zeros. The result will be a square matrix. This is useful for reducing the size of directed adjacency matrices for graphs or Markov models among other things.
This question is similar to this question, but requires a solution that works when we can't satisfy the condition: "when the i-th row is zeros, then i-th column is also zeros." I believe lacking this constraint makes the DeleteCases
and Select
-based methods unusable as they are offered. But there may be a way to adapt them to this more general case.
Currently my best method is the following:
First find the indices for which the respective matrix row AND column are zeros.
m = SomeSquareMatrix;
n = Length[m];
ids=Table[If[Total[m[[i]]]==0&&Total[m[[All,i]]]==0,{i},##&[]],{i,n}];
Note that Total
works great for probabilities and edge weights that are always positive, but could be replaced by
ids=Table[If[m[[i]]==ConstantArray[0, n]&&Flatten[m[[All,i]]]==ConstantArray[0, n],{i},##&[]],{i,n}];
The ##&[]
means that if the condition is false, return nothing. One you've identified the empty row-column combos, delete them:
m=Transpose[Delete[Transpose[Delete[m,ids]],ids]];
The last line is basically the same method used for this question and similar to the DeleteCases
approach, so it might actually be the best way to go. However, I suspect there is a superior method that combines identifying and removing the empty pairs of rows and columns.
Transpose[Delete[Transpose[Delete[mat, Position[Total[Unitize @ mat, {2}], 0]]], Position[Total[Unitize @ mat, {1}], 0]]]
work for you? $\endgroup$Intersection[Position[Total[Unitize @ mat, {2}], 0], Position[Total[Unitize @ mat, {1}], 0]]
? $\endgroup$ids
instead of a table ofIf
statements and it's actually slower. $\endgroup$