# Replacing nonzero elements of a matrix with corresponding elements of another matrix

Given an n-by-n matrix A with elements equal to either 0 or 1, I want to replace only nonzero elements (A_ij)'s by (b_ij) and leave 0's intact where (b_ij)'s are themselves elements of another n-by-n matrix B. I do it as following


a[A_, n_] :=
Table[If[A[[i, j]] == 1, A[[i, j]] = B[[i, j]], 0], {i,
n}, {j, n}]


Then by setting n=5, I get the following errors:

Part::partd: Part specification amat[[1,2]] is longer than depth of object. Set::setps: {{0,1,0,0,0},{1,0,1,0,0},{0,1,0,1,0},{0,0,1,0,1},{0,0,0,1,0}} in the part assignment is not a symbol.

How can I get rid of these errors? Is there a better way to do this procedure?

Thanks!

• You could do: newMatrix = A B Jan 13, 2022 at 23:38
• well, if you mean the tensor product of A & B, it doesn't do the job. Jan 13, 2022 at 23:52
• @Bill what you wrote is slightly different than what I have written in my question. But yes, the code I wrote first gives me the mentioned errors but then generates what I want. The problem I guess is the way I call b_ij from matrix B by writing B[[i,j]]. Jan 14, 2022 at 0:12

Firstly, define the matrices. Below I am doing $$(5 \times 5)$$ but the dimensions can easily be changed.

n = 5;
A = Table[RandomInteger[], {i, 1, n}, {j, 1, n}];
B = Table[b[i, j], {i, 1, n}, {j, 1, n}];
A // MatrixForm
B // MatrixForm


Then, you do the multiplication like so:

A B // MatrixForm


Comparing to the forms of the matrices A and B ,the result of the multiplication is the right answer.

Are there reasons that you want to use conditions? If, yes the following works fine:

(Table[If[A[[i, j]] == 0, 0, B[[i, j]]], {i, n}, {j,
n}]) // MatrixForm


and gives the same answer as the minimal approach which is the vanilla multiplication.

If you want to do in-place modification of A through a function call to a, then you have to tell a that you want to pass the matrix A by reference. You can do that by giving a the attribute HoldFirst (which in this context means call by reference for the first argument only).

So your function could look like this:

ClearAll[a];
SetAttributes[a, HoldFirst];
a[A_, B_] := Table[
If[A[[i, j]] == 1, A[[i, j]] = B[[i, j]], 0],
{i, Dimensions[A][[1]]}, {j, Dimensions[A][[2]]}
];


Here is a simple test problem:

A = RandomInteger[{0, 1}, {5, 5}]
B = RandomInteger[{1, 10}, {5, 5}]
a[A, B];
A


{{0, 1, 0, 1, 0}, {0, 1, 1, 0, 0}, {1, 0, 0, 0, 1}, {0, 1, 1, 1, 1}, {0, 0, 0, 0, 1}}

{{2, 6, 1, 2, 1}, {1, 2, 3, 2, 8}, {1, 1, 3, 10, 8}, {7, 6, 6, 8, 4}, {8, 9, 8, 2, 4}}

{{0, 6, 0, 2, 0}, {0, 2, 3, 0, 0}, {1, 0, 0, 0, 8}, {0, 6, 6, 8, 4}, {0, 0, 0, 0, 4}}

With Carl Woll's comment, you can also simply use this one:

ClearAll[a];
SetAttributes[a, HoldFirst];
a[A_, B_] := (A*=B);


If A is large and has only few nonzero entries, then you might want to consider to represent A as a SparseArray.