# How to replace anti diagonal elements of a matrix

I want to assign new values to the anti-diagonal elements of a square matrix m with the values of its diagonal elements. For that, I want to make use of ReplacePart, with the fact that

Part position specifications can be patterns

as stated in the documentation.

I want to use a command like this:

ReplacePart[m, (*pattern goes here*) :> Diagonal[m]〚i〛]


I need help with writing a pattern to access the anti-diagonal elements.

They have the property of i+j=Length[m]+1 but I can't find a way to implement it into a pattern match.

For example, with

m={
{100, 9, 3, 8, 0},
{4, 200, 6, 4, 9},
{5, 2, 300, 7, 8},
{7, 9, 6, 400, 5},
{6, 1, 4, 2, 500}
}


I want to produce the matrix

{
{100, 9, 3, 8, 100},
{4, 200, 6, 200, 9},
{5, 2, 300, 7, 8},
{7, 400, 6, 400, 5},
{500, 1, 4, 2, 500}
}

• use the replacement rule {i_, j_} /; j == Dimensions[m][[2]] + 1 - i :> Diagonal[m][[i]]?
– kglr
Jun 23, 2022 at 21:15
• Well I am a bit new to conditions and pattern matching. I didn't know how to write it down..
– tush
Jun 23, 2022 at 21:18

This is the kind of question that might trigger the "how-many-ways-can-you-do-it" game. I'll kick it off with this:

MapIndexed[ReplacePart[#1, -#2 -> #1[[#2[[1]]]]] &, m]


Explanation: The index of each row corresponds to the element that should be used as replacement as well as the one to be replaced (just count from the end). So, that suggested using MapIndexed. Then it's a matter of figuring out how to put the MapIndexed arguments into ReplacePart.

• The ReplacePart[]+MapIndexed[] is a good idea. Here's a slightly more compact version: ReplacePart[m, MapIndexed[Join[#2, -#2] -> #1 &, Diagonal[m]]]. Jun 23, 2022 at 21:46
• That’s excellent! Jun 23, 2022 at 21:49

From The Procedural Dodo:

If you can do it in place (destroying the orginal m), this will be fast:

Do[m[[i, -i]] = m[[i, i]], {i, Length@m}]


If m is a small matrix as in the example, then speed won't matter, but the code is easy to read.

To preserve m, use another variable:

m2 = m;
Do[m2[[i, -i]] = m2[[i, i]], {i, Length@m2}]


It's still relatively fast, but now m has to be copied.

Using ReplacePart:

ReplacePart[Association[Thread[Map[{# + 1, Length[m] - #} &, Range[0, Length[m] - 1]] -> Diagonal[m]]]][m] // MatrixForm


• We can subtract the anti-diagonal to remove it and then add the Reverse of diagonal.
m = {{100, 9, 3, 8, 0}, {4, 200, 6, 4, 9}, {5, 2, 300, 7, 8}, {7, 9,
6, 400, 5}, {6, 1, 4, 2, 500}};
antiDiagonal = Reverse[DiagonalMatrix@Diagonal@Reverse[m, {2}], {2}];
reverseDiagonal = Reverse[DiagonalMatrix@Diagonal@m, {2}];
m - antiDiagonal + reverseDiagonal
% // MatrixForm


• Or we can at first Reverse the matrix m to get the rm and subtract the Diagonal of rm and then Reverse.
m = {{100, 9, 3, 8, 0}, {4, 200, 6, 4, 9}, {5, 2, 300, 7, 8}, {7, 9,
6, 400, 5}, {6, 1, 4, 2, 500}};
rm = Reverse[m, {2}];
Reverse[rm - DiagonalMatrix@Diagonal@rm +
DiagonalMatrix@Diagonal@m, {2}]
% // MatrixForm


use element-wise operation.

1. keep the diag-matrix and reverse it.
anti = mat //
Diagonal // (*take diag*)
DiagonalMatrix // (*make mat*)
Map[Reverse] (*rev it*)


{{0, 0, 0, 0, 100}, {0, 0, 0, 200, 0}, {0, 0, 300, 0, 0}, {0, 400, 0, 0, 0}, {500, 0, 0, 0, 0}}

mask = IdentityMatrix[Length@mat]// (*np.eye*)
Map[Reverse] // (*rev*)


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

mat * mask + anti


{{100, 9, 3, 8, 100}, {4, 200, 6, 200, 9}, {5, 2, 300, 7, 8}, {7, 400, 6, 400, 5}, {500, 1, 4, 2, 500}}

idm = IdentityMatrix[Length@m]
(res = Reverse /@ (m idm) + m (-(Reverse /@ idm ) + 1)
) // MatrixForm


$$\left( \begin{array}{ccccc} 100 & 9 & 3 & 8 & 100 \\ 4 & 200 & 6 & 200 & 9 \\ 5 & 2 & 300 & 7 & 8 \\ 7 & 400 & 6 & 400 & 5 \\ 500 & 1 & 4 & 2 & 500 \\ \end{array} \right)$$

With[
Reverse[ReplaceAll[DiagonalMatrix[Function /@ Diagonal[m]], 0 -> Identity], 2]},


Making use of the method posted by ciao (in an answer to How to zero (or replace) the diagonal of a square matrix?)

With[{rm=Reverse@m, dr=Reverse@Diagonal@m},

(UpperTriangularize[rm,1] + LowerTriangularize[rm,-1] + DiagonalMatrix[dr])//Reverse

]


$$\left( \begin{array}{ccccc} 100 & 9 & 3 & 8 & 100 \\ 4 & 200 & 6 & 200 & 9 \\ 5 & 2 & 300 & 7 & 8 \\ 7 & 400 & 6 & 400 & 5 \\ 500 & 1 & 4 & 2 & 500 \\ \end{array} \right)$$

Alternatively:

Reverse[UpperTriangularize[Reverse@m,1] + LowerTriangularize[Reverse@m,-1]] +
SparseArray[Band[{1, 5}, Automatic, {1, -1}] -> Diagonal[m], {5, 5}]

(*
{
{100, 9, 3, 8, 100},
{4, 200, 6, 200, 9},
{5, 2, 300, 7, 8},
{7, 400, 6, 400, 5},
{500, 1, 4, 2, 500}
}
*)


Also related:

Is there a built in function to obtain the back diagonal of a matrix?

m =
{{100, 9, 3, 8, 0},
{4, 200, 6, 4, 9},
{5, 2, 300, 7, 8},
{7, 9, 6, 400, 5},
{6, 1, 4, 2, 500}};

With[{d = Diagonal @ m},
With[{r = Range @ Length @ d},
ReplacePart[Thread[Transpose[{r, Reverse @ r}] -> d]] @ m]] // MatrixForm