Changing the Diagonals of a Matrix with Mathematica
Is there an elegant way to change the diagonals of a matrix to a new list of values, the equivalent of Band with SparseArray?
Say I have the following matrix (see below)
(mat = Array[Subscript[a, ##] &, {4, 4}]) // Matri开发者_JAVA技巧xForm
and I'd like to change the main diagonal to the following to get "new mat" (see below)
newMainDiagList = Flatten@Array[Subscript[new, ##] &, {1, 4}]
I know it is easy to change the main diagonal to a given value using ReplacePart. For example:
ReplacePart[mat, {i_, i_} -> 0]
I'd also like not to be restricted to the main diagonal (in the same way that Band is not so restricted with SparseArray)
(The method I use at the moment is the following!)
(Normal@SparseArray[Band[{1, 1}] -> newMainDiagList] +
ReplacePart[mat, {i_, i_} -> 0]) // MatrixForm
(Desired Output is 'new mat')
Actually, you don't need to use Normal
whatsoever. A SparseArray
plus a "normal" matrix gives you a "normal" matrix. Using Band
is, on initial inspection, the most flexible approach, but an effective (and slightly less flexible) alternative is:
DiagonalMatrix[newDiagList] + ReplacePart[mat, {i_,i_}->0]
DiagonalMatrix
also accepts a second integer parameter which allows you to specify which diagonal that newDiagList
represents with the main diagonal represented by 0.
The most elegant alternative, however, is to use ReplacePart
a little more effectively: the replacement Rule
can be a RuleDelayed
, e.g.
ReplacePart[mat, {i_,i_} :> newDiagList[[i]] ]
which does your replacement directly without the intermediate steps.
Edit: to mimic Band
's behavior, we can also add conditions to the pattern via /;
. For instance,
ReplacePart[mat, {i_,j_} /; j==i+1 :> newDiagList[[i]]
replaces the diagonal immediately above the main one (Band[{1,2}]
), and
ReplacePart[mat, {i_,i_} /; i>2 :> newDiagList[[i]]
would only replace the last two elements of the main diagonal in a 4x4
matrix (Band[{3,3}]
). But, it is much simpler using ReplacePart
directly.
精彩评论