# Replace elements of a matrix with zeros using another matrix

I have a matrix Mat1 whos columns are ordered as :

Col = Flatten[Outer[{#2, #1} &, {0, 1}, Delete[Range[-2, 2, 1], 3]], 1]


and the rows are ordered as:

Rows = Flatten[Outer[{#1, #2} &, Delete[Range[-1, 1, 1], 2], Delete[Range[-1, 1, 1], 2]], 1]


The matrix is given as:

Mat1 = Outer[f[Flatten[{#1, #2}]] &, Col, Rows, 1]


$$\left( \begin{array}{cccc} f(\{-2,0,-1,-1\}) & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\f(\{-1,0,-1,-1\}) & f(\{-1,0,-1,1\}) & f(\{-1,0,1,-1\}) & f(\{-1,0,1,1\}) \\f(\{1,0,-1,-1\}) & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\f(\{2,0,-1,-1\}) & f(\{2,0,-1,1\}) & f(\{2,0,1,-1\}) & f(\{2,0,1,1\}) \\ f(\{-2,1,-1,-1\}) & f(\{-2,1,-1,1\}) & f(\{-2,1,1,-1\}) & f(\{-2,1,1,1\}) \\ f(\{-1,1,-1,-1\}) & f(\{-1,1,-1,1\}) & f(\{-1,1,1,-1\}) & f(\{-1,1,1,1\}) \\ f(\{1,1,-1,-1\}) & f(\{1,1,-1,1\}) & f(\{1,1,1,-1\}) & f(\{1,1,1,1\}) \\ f(\{2,1,-1,-1\}) & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \end{array} \right)$$

Another matrix Mat2 with a fewer elements is given as:

Mat2 = Outer[f[Flatten[{#1 , #2}]] &, {{-2, 0}, {1, 0}, {2, 1}}, {{-1, 1}, {1, -1}, {1, 1}}, 1]


$$\left( \begin{array}{ccc} f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \end{array} \right)$$

I want to make all the elements of the first matrix (Mat1) equal to zero that are not same as elements of Mat2. This will create a kind of a sparse matrix like:

$$\left( \begin{array}{cccc} 0 & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \end{array} \right)$$

How can I do this? (and for any general Range of col and Rows)

Edit: Building Mat1 with Outer for a large list of Rows and Col causes my system to hang and removes all variables from Mathematica. Outer carries out the arrangement of the elements at the positions I need in the matrix but it doesn't work for very big dimensions. I am only interested in the final sparse matrix with the elements at the positions dictated by the list of Rows and Col. Is there any way to get the final matrix by somehow using Rows and Col without the need to build Mat1?.

Update: An approach to use Col, Rows and the indices used to create Mat2 to get the desired sparse array without creating Mat1:

c2 = {{-2, 0}, {1, 0}, {2, 1}};
r2 = {{-1, 1}, {1, -1}, {1, 1}};
positions = Tuples[{Flatten@Position[Col, #]& /@ c2, Flatten@Position[Rows, #]& /@ r2}];

SparseArray[positions -> Flatten @ Mat2, Length /@ {Col, Rows}] // MatrixForm // TeXForm


$$\left( \begin{array}{cccc} 0 & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \\ \end{array} \right)$$

If you like, you can use f directly without having to use Mat2:

SparseArray[positions -> (f[Flatten[{Col[[#[]]], Rows[[#[]]]}]] & /@
positions), Length /@ {Col, Rows}] // MatrixForm // TeXForm


same result

### SparseArray

You can define a function f0 that takes two matrices as input and returns a SparseArray with the desired entries:

ClearAll[f0]
f0[m1_, m2_] := Module[{pos = Position[m1, Alternatives @@ Flatten[m2]]},
SparseArray[pos -> Extract[m1, pos], Dimensions[m1]]];

f0[Mat1, Mat2] // MatrixForm // TeXForm


$$\left( \begin{array}{cccc} 0 & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \\ \end{array} \right)$$

### ReplaceAll

Alternatively, define a function f1 that gives 0 for any input except one that matches elements of Mat2 and use it with ReplaceAll:

ClearAll[f1]
f1[x : Alternatives @@ Flatten[Mat2]] := x
f1[_] := 0;

Mat1 /. a_f :> f1[a] // MatrixForm // TeXForm


same result

You can also Map f1 on Mat1 at level 2:

Map[f1, Mat1, {2}] // MatrixForm // TeXForm


same result

or use it to construct the result directly without creating Mat:

Outer[f1@f[Flatten[{#1, #2}]] &, Col, Rows, 1] // MatrixForm // TeXForm


same result

• That is a very nice answer but my problem is in using Mat1 when I have a large list of Rows and Col. When I run the code Mat1 = Outer[f[Flatten[{#1, #2}]] &, Col, Rows, 1] my Mathematica hangs and maybe runs out of memory. Is there any way to get the final matrix by somehow using Rows and Col without the need to build Mat1?. Outer carries out the arrangement of the elements at the positions I need but it doesn't work for big dimensions. – jsid Sep 20 '18 at 18:53
• @jsid, please see the update. – kglr Sep 20 '18 at 19:13
• Great. Seems to work really good for now. Let me test it further. – jsid Sep 20 '18 at 19:35
• How time efficient will your method be for a matrix size of 16777216 by 1024, Is there a way to know this?. I had been running your code for an hour now but its still going on. – jsid Sep 20 '18 at 21:27
• @jsid, how big is Mat2? – kglr Sep 20 '18 at 21:35

Given:

Col = Flatten[Outer[{#2, #1} &, {0, 1}, Delete[Range[-2, 2, 1], 3]], 1];
Rows = Flatten[Outer[{#1, #2} &, Delete[Range[-1, 1, 1], 2], Delete[Range[-1, 1, 1], 2]], 1];


and:

c = {{-2, 0}, {1, 0}, {2, 1}};
r = {{-1, 1}, {1, -1}, {1, 1}};

Mat2 = Outer[f[Flatten[{#1 , #2}]] &, c, r, 1];


You can construct your desired sparse array with:

sparse = Module[{m = SparseArray[{}, {Length[Col], Length[Rows]}]},
m[[
Flatten @ Position[Col, Alternatives @@ c, 1],
Flatten @ Position[Rows, Alternatives @@ r, 1]
]] = Mat2;
m
];


Check:

sparse //MatrixForm //TeXForm


$$\left( \begin{array}{cccc} 0 & f(\{-2,0,-1,1\}) & f(\{-2,0,1,-1\}) & f(\{-2,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & f(\{1,0,-1,1\}) & f(\{1,0,1,-1\}) & f(\{1,0,1,1\}) \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & f(\{2,1,-1,1\}) & f(\{2,1,1,-1\}) & f(\{2,1,1,1\}) \\ \end{array} \right)$$

• I would like to ask you the same question as how time efficient will your method be for a matrix size of 16777216 by 1024?. I haven't yet run your code but would soon do. – jsid Sep 20 '18 at 21:31
• @jsid Depends on the dimensions of Mat2. What are they? Or equivalently, what are the lengths of c and r? – Carl Woll Sep 20 '18 at 21:36
• Length of c is 62250 and r is 1024 – jsid Sep 20 '18 at 21:48
• @jsid Those dimensions should not be a problem. What is f? – Carl Woll Sep 20 '18 at 22:02
• f is a function that is needed to be evaluated after the matrix has been formed. Each evaluation of f takes on an average about 0.02 seconds with Absolute Timing. – jsid Sep 20 '18 at 22:05

The second matrix is more like a list of elements you want to set to zero. Therefore I'd suggest

Mat2List = Flatten[Mat2]
Do[
If[MemberQ[Mat2List,Mat1[[j,i]]],
(*then we are good to go*),
Mat1[[j,i]] = 0
]
, {i, 1, Length[Rows]},
{j, 1, Length[Col]}
]


Which checks for all members of Mat1 whether they are in Mat2

• Your code is working but when I increase the dimensions of the Rows and Col my Mathematica hangs and all the variables are removed. How can I use this for big matrices?. I only need the final matrix with the zeros and the elements of Mat2 at correct positions in the matrix. I do not need Mat1, is there a way to create such sparse matrix?. – jsid Sep 20 '18 at 17:25