# matrix Crop (remove leading and trailing zeroes in matrix)

I have some matrices that have 0's around them, for example, give such a matrix

MatrixForm[ mat = ArrayPad[{{1, 2, 3}, {0, 0, 0}, {7, 8, 0}}, {{1, 2}, {2, 3}}]]


$$\begin{array}{cccccccc} 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 2 & 3 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 7 & 8 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ \end{array}$$

Expect to get {{1, 2, 3}, {0, 0, 0}, {7, 8, 0}}. One way is to use image processing, but it's inefficient

ImageData[ImageCrop[Image[mat]]] // Round


{{1, 2, 3}, {0, 0, 0}, {7, 8, 0}}

Do[ImageData[ImageCrop[Image[mat, "Real"]]] // Round, 10^3] // AbsoluteTiming

Might there be a faster method?

• Have you already seen resources.wolframcloud.com/FunctionRepository/resources/… ? Jul 4 at 13:24
• Take[mat,##]&@@CoordinateBounds@SparseArray[mat]@"NonzeroPositions" Jul 4 at 13:39
• @chyanog Wow, this is really fast, why not post it as an answer? Jul 4 at 13:44

matrixCrop[mat_?MatrixQ] :=
Take[mat, ##] & @@ CoordinateBounds@SparseArray[mat]@"NonzeroPositions";

MatrixForm[mat = ArrayPad[{{1, 2, 3}, {0, 0, 0}, {7, 8, 0}}, {{1, 2}, {2, 3}}]]
Do[matrixCrop[mat], 10^5] // AbsoluteTiming


{0.694102, Null}

If the core matrix isn't large, the following should be efficient:

RepeatedTiming@
Normal@With[{m = SparseArray@mat},
m[[##]] & @@ Span @@@ MinMax /@ Transpose@m@"ExplicitPositions"]
(* {0.0000115352, {{1, 2, 3}, {0, 0, 0}, {7, 8, 0}}} *)


If the core is large, the following should not be bad:

pos = m |-> Position[m, Except@{0 ..}, {1}, 1, Heads -> False][[1, 1]];
mat[[pos@mat ;; -pos@Reverse@mat,
pos[mat\[Transpose]] ;; -pos@Reverse[mat\[Transpose]]]] // RepeatedTiming
(* {0.0000268782, {{1, 2, 3}, {0, 0, 0}, {7, 8, 0}}} *)


If there is a built-in function, surely someone will bring it up, but in any case, here is one implementation:

aux1[{}]={};
aux1[l_List]:=If[MatchQ[First[l],{0...}],aux1[Rest[l]],l];
aux2[l_List]:=Reverse[aux1[Reverse[aux1[l]]]];
crop[m_?MatrixQ]:=Transpose[aux2[Transpose[aux2[m]]]];


crop[mat]