# Replacing parts of a Matrix with lists

I want to use lists to easily replace parts of a matrix. As an example, I want to replace the code

ReplacePart[{{1, 0}, {0, 1}}, {{1, 1} -> 13, {1, 2} -> 14}]


by something like

ReplacePart[{{1, 0}, {0, 1}}, {{1, 1}, {1, 2}} -> {13, 14}]


which doesn't work. For a general matrix m, I want to, given a list of indices of the type (x,y), li and a list of replacement values, lr, use something like

ReplacePart[m, li -> lr}]


Any idea how to do this?

ReplacePart[{{1, 0}, {0, 1}}, Thread[{{1, 1}, {1, 2}} -> {13, 14}]]


so

ReplacePart[m, Thread[li -> lr]]


in general.

But a CompiledFunction will probably do the job quicker because Thread[li -> lr] unpacks arrays. Let's see.

cReplacePart =
Compile[{{A0, _Real, 2}, {pos, _Integer, 2}, {val, _Real, 1}},
Block[{A = A0},
If[
1 <= Max[pos[[All, 1]]] <= Dimensions[A0][[1]] &&
1 <= Max[pos[[All, 2]]] <= Dimensions[A0][[2]],
Do[
A[[CompileGetElement[pos, i, 1],
CompileGetElement[pos, i, 2]]] = CompileGetElement[val, i],
{i, 1, Min[Length[pos], Length[val]]}
]
];
A
],
CompilationTarget -> "C",
RuntimeOptions -> "Speed"
];


And indeed, it's 100 times as fast:

n = 1000;
m = 1000000;
A = RandomReal[{-1, 1}, {n, n}];
li = RandomInteger[{1, n}, {m, 2}];
lr = RandomReal[{-1, 1}, m];

B = ReplacePart[A, Thread[li -> lr]]; // AbsoluteTiming // First
cB = cReplacePart[A, li, lr]; // AbsoluteTiming // First
Max[Abs[B - cB]]


4.91402

0.047307

0.

One may also use SparseArray; this is only a tiny bit slower than the compiled approach:

spB = A SparseArray[li -> 0., Dimensions[A], 1.] +
SparseArray[Reverse@li -> Reverse@lr, Dimensions[A], 0.]; //
AbsoluteTiming // First
Max[Abs[B - spB]]


0.086657

0.

ReplacePart has a undocumented four variables form that permits this :

oldValuesList = {{1, 0}, {0, 1}}
newValuesList = {13, 14}
modifiedPositionsList = {{1, 1}, {1, 2}}
newValuesPositions = (* gives the origin of the new data *)
List /@ Range[Length[newValuesList]] (* simply {{1},{2}} *)

ReplacePart[oldValuesList
, newValuesList
, modifiedPositionsList
, newValuesPositions]


{{13, 14}, {0, 1}}

I have retrieved this information in Michael Trott' s book "Mathematica Guidebook for Programming" page 628.

According to this It was documented until Version 5.2.

EDIT

ReplacePart is known to be often not memory/speed optimal. It may be slow and memory consuming with large data sets.

Henrik Schumacher's comments below confirm this in this particular case.

• I would have done newValuesPositions = Transpose[{Range[Length[newValuesList]]}] myself. Mar 24 '20 at 14:25
• I would do Partition[Range[Length[newValuesList]], 1]. Mar 24 '20 at 14:35
• Beware, this applies the changes in reverse order! And it's even slower than Thread... Mar 24 '20 at 14:37
• It's really awfully slow, like several minutes(!) for 1000000 replacements in a 1000 by 1000 matrix (which can actually be done in 0.05 seconds). So I really do not recommend to use the for-argument version for larger data. This is so unfortunate because I really miss this functionality. One may use SparseArray`, but it is not as well-suited for dense matrices. Mar 24 '20 at 14:50