Replacing parts of a Matrix with lists
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[[Compile`GetElement[pos, i, 1],
Compile`GetElement[pos, i, 2]]] = Compile`GetElement[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.