I've got following data I'm reading from a file:
data = {{{2013, 1, 11}, 4},
{{2013, 1, 12}, 1},
{{2013, 1, 14}, 1},
{{2013, 1, 16}, 2},
{{2013, 1, 18}, 1},
{{2013, 1, 19}, -1, 16},
{{2013, 1, 20}, 2},
{{2013, 1, 21}, 2}
};
(notice that list elements may have an extra item.) Now I want a similar datelist with each time the accumulated sum (ignoring possible third elements after a data item, like the 16 in the example). Procedurally I'd do something like this:
tally = 0;
datelisttally = {};
For[i = 1, i <= Length[data],
tally = tally + data[[i]][[2]];
datelisttally = Append[datelisttally, {data[[i]][[1]], tally}]; i++];
DateListPlot[datelisttally, PlotRange -> {0, Automatic}, Joined -> True]
but I'd like to learn the best way to do this with functional programming, best being the fastest. (The file may hold several thousands of items.)
update
I've benchmarked the 3 current solutions, and these are the results (list length = 1 million elements, averaged over 50 runs):
- Szabolcs's: 0.33 s
- PlatoManiac's: 0.54 s
- Leonid's: 3.33 s
Accumulatefunction. (which reminds me of what a fellow student of mine said: "programming is like magic. It's easy once you know the magic words.") – stevenvh Jan 14 '13 at 15:45Accumulate, we usedFoldList(like Leonid's answer). It's likeAccumulategeneralized for operations other thanPlus. – Szabolcs Jan 14 '13 at 15:48Accumulateis optimized on packed arrays, which is one of the good reasons to use it in place ofFoldListfor running sums. In this case, since thedataacc[[All, 2]]is not going to be packed at the start, it may improve the performance to pack it first, before the call toAccumulate. The resulting list is going to be unpacked during an assignment though, so I don't know how much speed improvement this may bring, if any. – Leonid Shifrin Jan 14 '13 at 15:52AccumulateorFoldListhave to do. Adding integers is supposedly a much faster operation than date conversion. – Leonid Shifrin Jan 14 '13 at 15:56