Re: Combining data from indexed lists efficiently
- To: mathgroup at smc.vnet.net
- Subject: [mg106253] Re: [mg106182] Combining data from indexed lists efficiently
- From: "Steve W. Brewer" <steve at take5.org>
- Date: Wed, 6 Jan 2010 06:00:26 -0500 (EST)
- References: <201001041059.FAA21250@smc.vnet.net> <4B42617D.2080204@wolfram.com>
Thanks everyone who responded!
I ended up going with Daniel's solution because it turned out to be easiest
to adapt to my specific situation. However, I did need to make a couple of
changes to Daniel's code.
One of my derived-value functions (f2[]) uses the result of another
derived-value function (f1[]). I could do something like this ...
valueTables[ lists,
{ f1[ #[[1]], #[[2]] ] &,
f2[ f1[ #[[1]], #[[2]] ], #[[3]] ] & }]
... but then f1[] is evaluated twice for each sample. By changing
vtj = Take[valtab[[j,2]],ll];
to
vtj := valtab[[j,2]];
the complete result vector is available to my derived-value functions,
including results from previously computed functions. So now I can write
valueTables[ lists,
{ f1[ #[[1]], #[[2]] ] &,
f2[ #[[4]], #[[3]] ] & }]
where #[[4]] is the result from f1.
I also discovered that some of my data had a few duplicate indices, which
didn't bother my original code but messed up the recordkeeping in the
subindices list in this approach. I added a couple of lines of code to that
Do loop to skip over any duplicate indices encountered:
Do[
list = lists[[j]];
previpos = 0;
Do[
listi = list[[i]];
ipos = indexset[listi[[1]]];
If [!IntegerQ[ipos] || ipos <= previpos, Continue[]];
subindices[[ipos]] += 1;
valtab[[ipos,2,subindices[[ipos]]]] = listi[[2]];
previpos = ipos;
,{i,Length[list]}];
,{j,ll}];
Final result: My previous code took at least a couple of hours to run on my
machine. The new code takes 19.5 seconds!
Here's the complete code with my changes:
indexesToUse[lists_List] := Apply[Intersection,Map[#[[All,1]]&,lists]]
initValueTable[indices_,len_] :=
Table[{indices[[j]],ConstantArray[0,len]}, {j,Length[indices]}]
valueTables[lists_List,funcs_List] := Module[
{indices,valtab,subindices,ll,list,listi,indexset,ipos,vtj},
ll = Length[lists];
indices = indexesToUse[lists];
valtab = initValueTable[indices,ll+Length[funcs]];
subindices = ConstantArray[0,Length[indices]];
Do[indexset[indices[[j]]] = j, {j,Length[indices]}];
Do[
list = lists[[j]];
previpos = 0;
Do[
listi = list[[i]];
ipos = indexset[listi[[1]]];
If [!IntegerQ[ipos] || ipos <= previpos, Continue[]];
subindices[[ipos]] += 1;
valtab[[ipos,2,subindices[[ipos]]]] = listi[[2]];
previpos = ipos;
,{i,Length[list]}];
,{j,ll}];
Clear[indexset];
Do[
vtj := valtab[[j,2]];
Do[
valtab[[j,2,ll+i]] = funcs[[i]][vtj];
,{i,Length[funcs]}];
,{j,Length[valtab]}];
valtab
]
Steve W. Brewer
- References:
- Combining data from indexed lists efficiently
- From: "Steve W. Brewer" <steve@take5.org>
- Combining data from indexed lists efficiently