I have a matrix which is constructed element by element through some iterations, and thus can be non-square. If it’s not square, then I want to make it square filling with 0. Is there a function to determine if a matrix is square?

I was thinking of something like this:

(* If determinant of matrix is possible, then fill with 0s, else do nothing. *)

If[Det[matrix]=Indeterminate,Fillwithzeros[matrix]]

I’m pretty sure Det[matrix] = Indeterminate is not a correct way to express my thoughts, so maybe you could help me out with my syntax or even suggest a better way to do it 😀

Thanks!

=================

1

What about Dimensions and some ArrayPad?

– Yves Klett

May 13 ’14 at 17:14

1

Compare Equal @@ Dimensions[{{0, 0}, {0, 0}}] and Equal @@ Dimensions[{{0, 0}, {0, 0}, {0, 0}}] 🙂

– Öskå

May 13 ’14 at 17:16

1

BTW: Det[matrix]=Indeterminate is trying to set the value of Det[matrix] equal to Indeterminate not test if it is. Testing if A equals B is written ==. However Indeterminate is a symbol so you need === in that case.

– Ymareth

May 13 ’14 at 17:27

1

@SaxoMikoMola and where would you like the fill the rectangle matrix?

– Öskå

May 13 ’14 at 17:40

2

In V10, there is/will be SquareMatrixQ

– Michael E2

May 13 ’14 at 18:08

=================

3 Answers

3

=================

If you are concerned about the case where you list of lists has unequal length sublists then you should first do MatrixQ:

MatrixQ[#] && MatchQ[ Dimensions[#] , {_ ..}] &@ RandomInteger[10,{3,3}]

True

or

MatrixQ[#] && Equal @@ Dimensions@# &@{{1, 2, 1}, {1, 4, 4}, {4, 5, 4}}

True

padding

Normal@SparseArray[#, ConstantArray[Max@Dimensions@#,2]] &@ RandomReal[1, {4, 2}]

Here is what I would propose, but it can probably be faster:

filling[mat_] := If[Equal @@ Dimensions@mat, mat,

If[Less @@ Dimensions@mat,

Join[mat, SparseArray[{}, {1, Max@Dimensions@mat}]],

PadRight[mat[[#]], Max@Dimensions@mat] & /@ Range@Max@Dimensions@mat]]

where the test on the matrix squarenessÂ¹ is not needed.

mat[m_, n_] := RandomInteger[{0, 10}, {m, n}]

Examples:

SeedRandom@10;

mat[3, 2] // MatrixForm

(10109786)\left(

\begin{array}{cc}

10 & 10 \\

9 & 7 \\

8 & 6 \\

\end{array}

\right)

SeedRandom@10;

filling[mat[3, 2]] // MatrixForm

(10100970860)\left(

\begin{array}{ccc}

10 & 10 & 0 \\

9 & 7 & 0 \\

8 & 6 & 0 \\

\end{array}

\right)

SeedRandom@2;

mat[2, 3] // MatrixForm

(845474)\left(

\begin{array}{ccc}

8 & 4 & 5 \\

4 & 7 & 4 \\

\end{array}

\right)

SeedRandom@2;

filling[mat[2, 3]] // MatrixForm

(845474000)\left(

\begin{array}{ccc}

8 & 4 & 5 \\

4 & 7 & 4 \\

0 & 0 & 0 \\

\end{array}

\right)

Timings:

filling[mat[10000, 9999]]; // AbsoluteTiming

{1.897158, Null}

filling[mat[9999, 10000]]; // AbsoluteTiming

{1.651018, Null}

filling[mat[10000, 10000]]; // AbsoluteTiming

{1.253314, Null}

The last being approximately equivalent to mat[10000, 10000]; // AbsoluteTiming

Â¹ squareQ = Equal @@ Dimensions@# &;

pad = With[{dim = Dimensions@#},

If[Equal @@ dim, #, ArrayPad[#, {{0, 0}, Abs[dim – Max@dim]}\[Transpose]]]] &;

pad @ RandomReal[1, {4, 2}] // MatrixForm

Edit this version is going to work with multidimensional matrices too 🙂

pad = With[{dim = Dimensions@#},

If[Equal @@ dim, #, ArrayPad[#, {0 dim, Abs[dim – Max@dim]}\[Transpose]]]] &;

pad @ RandomReal[1, {3, 2, 3, 2}] // MatrixForm

Damn, I was really wondering how to use ArrayPad, I guess I was missing the Abs[dim – Max@dim] part.. 🙂

– Öskå

May 13 ’14 at 19:21

@Öskå Thanks 😛 I was looking for more compact way but I’ve failed 🙁

– Kuba

May 13 ’14 at 19:23

It’s already quite compact compared to mine 😛 I feel stupid now for not handling ArrayPad 🙂

– Öskå

May 13 ’14 at 19:25

1

@Öskå now George made me stupid ;P

– Kuba

May 13 ’14 at 19:41