Additive SparseArray Assembly
There is actually an undocumented System Option that tells Mathematica to do this automatically. The default behavior:
ind = {{3, 1}, {3, 3}, {1, 3}, {2, 1}, {3, 2}, {3, 1}, {3, 2}, {3, 3}, {1, 3}, {3, 1}};
val = {1, 1, 3, 0, 3, 4, 3, 1, 1, 1};
SparseArray[ind -> val] // Grid
$ \begin{matrix} 0 & 0 & 3 \\ 0 & 0 & 0 \\ 1 & 3 & 1 \end{matrix} $
Now with our "magic" Option (learned from Oliver Ruebenkoenig):
SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> 1}];
(* equivalently:
SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> Total}] *)
SparseArray[ind -> val] // Grid
$ \begin{matrix} 0 & 0 & 4 \\ 0 & 0 & 0 \\ 6 & 6 & 2 \end{matrix} $
Arbitrary functions are accepted by version 9 and later; see: Optimising 2D binning code
SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> (# - +##2 &)}];
SparseArray[ind -> val] // Grid
$\begin{matrix} 0 & 0 & 2 \\ 0 & 0 & 0 \\ -4 & 0 & 0 \\ \end{matrix}$
To restore the default behavior set:
SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> 0}];
(* equivalently:
SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> First}] *)
To encapsulate this setting, use Internal`WithLocalSettings
: SetOptions locally?
n=4;
ind = RandomInteger[{1, n}, {10, 2}]
val = RandomReal[{-1, 1}, Length[ind]]
#[[1, 1]] -> Total[#[[;; , 2]]] & /@ GatherBy[Thread[{ind, val}], First]
a = SparseArray[%, {n, n}]
or quite ugly but compact:
b = SparseArray[#, {n, n}] & /@ Thread[ind -> val] // Total
a == b
True