Re: Efficient function to accumulate a list of

• To: mathgroup at smc.vnet.net
• Subject: [mg132514] Re: Efficient function to accumulate a list of
• From: Bob Hanlon <hanlonr357 at gmail.com>
• Date: Fri, 4 Apr 2014 03:57:58 -0400 (EDT)
• Delivered-to: l-mathgroup@mail-archive0.wolfram.com
• Delivered-to: l-mathgroup@wolfram.com
• Delivered-to: mathgroup-outx@smc.vnet.net
• Delivered-to: mathgroup-newsendx@smc.vnet.net
• References: <20140403061721.737146A1A@smc.vnet.net>

```Your function does not work as described. For comparison with other
approaches, I have simplified it and modified it to do what you described.

Clear[particleToDensity, particleToDensity2, particleToDensity3]

Use Module to localize the transient variable names, delete the unnecessary
Round and If, and use lower case letter to start a user-defined function
(avoid potential future name conflict with built-in functions):

particleToDensity[particles_,
arrayDimensions_: {144, 300}] :=
Module[{arr, l, tp},
arr = ConstantArray[0, arrayDimensions];
For[l = 1, l <= Length[particles], l++,
tp = particles[[l]];
arr[[tp[[2]], tp[[3]]]] += tp[[1]]];
arr]

Use Map rather than For loop:

particleToDensity2[particles_,
arrayDimensions_: {144, 300}] :=
Module[{arr},
arr = ConstantArray[0, arrayDimensions];
(arr[[#[[2]], #[[3]]]] += #[[1]]) & /@
particles;
arr]

Use SparseArray

particleToDensity3[particles_,
arrayDimensions_: {144, 300}] :=
SparseArray[{#[[1, 2]], #[[1, 3]]} -> Total[#[[All, 1]]] & /@
GatherBy[particles, #[[{2, 3}]] &], arrayDimensions]

data = {{3.6, 7, 4}, {3.4, 8, 6}, {2.1, 7, 4}};

t1 = Timing[arr1 = particleToDensity[data];];

t2 = Timing[arr2 = particleToDensity2[data];];

t3 = Timing[arr3 = particleToDensity3[data];];

Verifying that the arrays are equivalent

arr1 == arr2 == arr3

True

Map is marginally quicker and the sparse array approach is much quicker

{t1[[1]]/t2[[1]], t1[[1]]/t3[[1]]}

{1.03, 2.7}

However, if the array is relatively dense

data = Table[{
RandomReal[{0, 5}],
RandomInteger[{1, 144}],
RandomInteger[{1, 300}]},
{10000}];

t1 = Timing[arr1 = particleToDensity[data];];

t2 = Timing[arr2 = particleToDensity2[data];];

t3 = Timing[arr3 = particleToDensity3[data];];

Verifying that the arrays are equivalent

arr1 == arr2 == arr3

True

Map is now noticeably quicker but the SparseArray became noticeably slower

{t1[[1]]/t2[[1]], t1[[1]]/t3[[1]]}

{1.3822, 0.7310}

Bob Hanlon

On Thu, Apr 3, 2014 at 2:17 AM, <julian.w.francis at gmail.com> wrote:

> Dear all,
>
> I am struggling with how to convert a list of (value, coords) tuples into
> an array such that the an element in the array should represent the sum of
> all value elements in that list with matching coords, and zero if no
> matches, e.g.
>
> { {3.6, 7,4}, {3,4, 8,6}, {2.1, 7,4} }
>
> if it were a 10X10 element array would become all zero's, except element
> (7,4)->(3.6+2.1) and (8,6)->3.4
>
> I've got some code which does what I want:
>
> ParticleToDensity[particles_] := (
>   arr = ConstantArray[0, {144, 300}];
>   For[l = 1, l < NoParticles, l++,
>    (tp = particles[[l]];
>     If[tp[[2]] != 0,
>      arr[[Round[tp[[3]]], Round[tp[[2]]]]] += tp[[1]]]
>     )];
>   arr)
>
> So, the argument to the function is a list of "particles", and the first
> element of this particle is the value in the array I'd like to accumulate,
> and the next two elements in that particle say where in the array they
> should be accumulated.
>
> It seems to work, but it is slow. I can see that this isn't really the
> Mathematica way of doing things, but I'm struggling to think of a better
> way.
>
> For reference, NoParticles is typically set to something like 10,000, and
> it takes about 0.1 secs to process on my machine. However this needs to be
> done frequently, hence I am hoping for a better way.
>
>
>
> Any help greatly appreciated.
>
> Thanks,
> Julian.
>
>

```

• Prev by Date: Re: Solve output depends on previous attempt with bad syntax
• Next by Date: Re: Solve output depends on previous attempt with bad syntax
• Previous by thread: Efficient function to accumulate a list of {value,coord} into array
• Next by thread: Re: Efficient function to accumulate a list of {value,coord} into array