7
$\begingroup$

Given a square matrix like

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

I want to expand it to a 5x5 matrix

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

In MATLAB, one can do

m[[4,4]]=1; m[[5,5]]=1; 

which also automatically "fills in" the zeros.

$\endgroup$
4
  • $\begingroup$ Check SparseArray documentation $\endgroup$ Commented Oct 15, 2023 at 22:18
  • $\begingroup$ SparseArray will not do it ether. $\endgroup$ Commented Oct 15, 2023 at 22:29
  • 1
    $\begingroup$ Don't discount @yarchik 's advice: SparseArray[m, {5, 5}, 0] // Normal. $\endgroup$ Commented Oct 16, 2023 at 0:55
  • $\begingroup$ It seems to me that an important point here is whether you want to expand m ('in-place modification'), and which I suspect MATLAB is doing, or whether you want to create a new matrix k. For in-place modification, maybe m//=MapAt[1&,{{4,4},{5,5}}]@ArrayPad[#,{0,2}]& (using ApplyTo) $\endgroup$ Commented Oct 17, 2023 at 10:48

8 Answers 8

4
$\begingroup$

You can't really do that in Mathematica as the new position must be there already. Btw, I never really like this feature in Matlab. I do not think it is good. Because someone by mistake could do this, using wrong index, and not know about it, as Matlab will silently expands the matrix. In Mathematica you get a real error message, which is much better.

Explicit is always better than implicit when it comes to coding.

But easy enough to make your own little expand function.

(m={{1,2,3},{4,5,6},{7,8,9}})//MatrixForm 

Mathematica graphics

myExpand[m,4]//MatrixForm 

Mathematica graphics

myExpand[m,5]//MatrixForm 

Mathematica graphics

myExpand[m, 2] // MatrixForm 

Mathematica graphics

myExpand[m, 8] // MatrixForm 

Mathematica graphics

code

myExpand[mat_?MatrixQ, (newSize_Integer)?Positive] := Module[{t, currentSize = Length@mat}, If[newSize <= currentSize, t = mat[[1 ;; newSize, 1 ;; newSize]] , t = Table[0, {newSize}, {newSize}]; t[[1 ;; currentSize, 1 ;; currentSize]] = mat ]; t ] 

ps. If you wanted 1 on diagonal and not zeros, then just replace the line

t = Table[0, {newSize}, {newSize}]; 

with

t = IdentityMatrix[newSize]; 

so now myExpand[m, 5] // MatrixForm gives

Mathematica graphics

As you can see from the others answers, in Mathematica, there are always at least 10 different ways to do the same thing, and you pick the one that you prefer most.

$\endgroup$
4
  • $\begingroup$ Very nice! Thank you. $\endgroup$ Commented Oct 15, 2023 at 22:56
  • 2
    $\begingroup$ You can also just use ArrayPad or PadRight. $\endgroup$ Commented Oct 15, 2023 at 23:45
  • $\begingroup$ Is there a reason for Table[0, {newSize}, {newSize}] instead of ConstantArray[0,newSize,newSize] ? (except that ConstantArray still is not compileable) $\endgroup$ Commented Oct 16, 2023 at 7:34
  • 1
    $\begingroup$ @JulienKluge No reason., There are at least 10 different ways to make a matrix of zeros. See this and I just picked one that seemed most easy for general public :) $\endgroup$ Commented Oct 16, 2023 at 7:41
8
$\begingroup$

See the docs for ArrayFlatten

k = ArrayFlatten[{{m, 0}, {0, IdentityMatrix[2]}}]; k // MatrixForm 

$$\left( \begin{array}{ccccc} 1 & 2 & 3 & 0 & 0 \\ 4 & 5 & 6 & 0 & 0 \\ 7 & 8 & 9 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 1 \\ \end{array} \right)$$

$\endgroup$
4
  • $\begingroup$ hi. fyi, op wanted to expand with all zeros. $\endgroup$ Commented Oct 15, 2023 at 23:34
  • $\begingroup$ k = ArrayFlatten[{{m, 0}, {0, ConstantArray[0, {2, 2}]}}]; $\endgroup$ Commented Oct 16, 2023 at 3:36
  • $\begingroup$ @Syed & Nasser Thank you for your comments, but I see 1's on the diagonal in the OP. The OP shows an example of trying to insert the 1's using MMA's double square-bracket notation, but in the Matlab syntax. The OP does mention automatic filling in the zeros, but those zeros are in the 4th and 5th rows and columns, not on the diagonal. $\endgroup$ Commented Oct 16, 2023 at 5:43
  • $\begingroup$ You might be right. I just read the title of the question saying "fill with zeros". But now looking at it more, may they wanted like you show. I'll update a note to my answer now just in case. $\endgroup$ Commented Oct 16, 2023 at 6:34
8
$\begingroup$
BlockDiagonalMatrix[{m, IdentityMatrix[2]}] 

To get a "normal" matrix:

Normal[BlockDiagonalMatrix[{m, IdentityMatrix[2]}]] (* {{1, 2, 3, 0, 0}, {4, 5, 6, 0, 0}, {7, 8, 9, 0, 0}, {0, 0, 0, 1, 0}, {0, 0, 0, 0, 1}} *) 

If your example was just accidentally a diagonal block matrix, and all you need is to pad out a matrix with zeros to get a certain size which you will then update, then you can just use ArrayPad or PadRight:

ArrayPad[m, {{0, 2}, {0, 2}}] 

or

PadRight[m, {5, 5}] 

Of course, these don't update m, so if part of your question was updating, then just redefine m:

m = ArrayPad[m, {{0, 2}, {0, 2}}] 

or

m = PadRight[m, {5, 5}] 

To your comment that "SparseArray will not do it", I have to disagree. The following will give you a sparse array version of your padded m:

SparseArray[m, {5, 5}] 

or

m = SparseArray[m, {5, 5}] 

With the latter, you can now do

m[[4,4]] = 1 
$\endgroup$
4
$\begingroup$
MapAt[1 &, ArrayPad[m, {0, 2}], {{4, 4}, {5, 5}}] 

or

ReplaceAt[ArrayPad[m, {0, 2}], _ :> 1, {{4, 4}, {5, 5}}] 

and

ReplacePart[ArrayPad[m, {0, 2}], {4, 4} | {5, 5} :> 1] 

give

enter image description here

$\endgroup$
4
$\begingroup$

We can use SparseArray + Band to modify the dimensions and specify/modify entries of an input matrix in a single step:

ClearAll[modifyArray] modifyArray = SparseArray[Append[#2, Band[{1, 1}] -> {#}], ##3] &; 

Examples:

m = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; rules = {{2, 1} -> 100, {4, 4} -> FOO, {5, 5} -> BAR, {6, 2} -> 62}; modifyArray[m, rules]// MatrixForm 

enter image description here

modifyArray[m, rules, {8, 7}] // MatrixForm 

enter image description here

modifyArray[m, rules, Automatic, Z] 

enter image description here

$\endgroup$
3
$\begingroup$

Another way, using Reap and Sow:

myMatExpand[mat_?MatrixQ, nsize_Integer?Positive]/; Length[mat] < nsize := Flatten[Reap[ Do[Sow[Join[l, Array[0 &, nsize - Length@mat]]], {l, mat}]; Do[Sow[ReplacePart[Array[0 &, nsize], i -> 1]], {i, Take[Range[nsize], Length[mat] - nsize]}];][[2]], 1] 

Testing myMatExpand:

myMatExpand[m, 8] // MatrixForm 

enter image description here

Another way is as follows:

myMatExpand[mat_?MatrixQ, nsize_Integer?Positive] /; Length[mat] < nsize := Join[Map[Join[#, Array[0 &, nsize - Length@mat]] &, mat], Take[IdentityMatrix[nsize], Length@mat - nsize]] 
$\endgroup$
2
$\begingroup$

Using MapIndexed:

expandMatrix[m_?MatrixQ, list_?VectorQ] := Flatten[#, 1] &@MapIndexed[#2 -> #1 &, m, {2}]~Join~list // SparseArray // Normal 

Usage:

expandMatrix[m, {{4, 4} -> 1, {5, 5} -> 1}] // MatrixForm 

enter image description here

$\endgroup$
1
$\begingroup$

"You can use 1 or 0 in diagonal: "

ExpandM[m_,n_,k_]:=(d=Dimensions[m][[1]];(Table[If[j ≤ d ,a=m[[j]];Do[a=Insert[a,0,i],{i,d+1,n}];a,Insert[ConstantArray[0,n-1],k,j]],{j,1,n}])//MatrixForm) 

Diagonal 1 :

ExpandM[m,5,1] 

enter image description here

Diagonal 0 :

ExpandM[m,5,0] 

Mathematica graphics

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.