What is the Canonical way to map a function to only the diagonal elements of a matrix?

For example, given

 A = {{E, 0}, {0, E}}

I wanted to take the log of the diagonal elements only to obtain {{1, 0}, {0, 1}}

I came up with these

 MapAt[Log[#] &, A, Table[{i, i}, {i, Length[A]}]]

Mathematica graphics

  result = Log[Diagonal[A]];
  ReplacePart[A, {i_, i_} :> result[[i]]]

Mathematica graphics

Since in Mathematica the rule of thumb is that there should be at least 10 different ways to do the same thing, I think there is room to find a better approach.

  • 1
    $\begingroup$ Maybe using MapIndexed rather than MapAt ? $\endgroup$ – b.gates.you.know.what Apr 20 '20 at 10:23
  • 3
    $\begingroup$ Also possible : ReplacePart[A, {i_, i_} :> Log[A[[i, i]]]] $\endgroup$ – andre314 Apr 20 '20 at 10:34

Using b.gates.you.know.what's idea:

With[{f = Log}, 
     MapIndexed[Function[{x, id}, If[Equal @@ id, f[x], x]], A, {2}]]

Using an undocumented function:

res = A;
With[{f = Log}, LinearAlgebra`Private`SetMatrixDiagonal[res, f[Diagonal[res]]]];

Note that this function modifies matrices given to it, so you'll need to make a copy if you still need the starting matrix.


A modification of a method given by Leonid Shifrin in Mathematica programming: an advanced introduction

A// MapThread[ReplacePart, {#, Log@Diagonal[#], Range[Length@#]}]&

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

There is a discussion in this old SO question: Changing the Diagonals of a Matrix with Mathematica


I don't know if there are 10 different ways, but here's a third.

Start with A and subtract off the diagonal, modify the diagonal with your function (Log) and add it back in:

A - DiagonalMatrix[Diagonal[A]] + DiagonalMatrix[Log[Diagonal[A]]]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.