I have pairs of numbers {a1, b1}
, {a2, b2}
, {a3, b3}
, ..., {aN, bN}
What is the shortest way to compute and plot {a1, b1}
, {a2, b1+b2}
, {a3, b1+b2+b3}
,....?
Accumulate@Array[b, {3}]
(* {b[1], b[1] + b[2], b[1] + b[2] + b[3]} *)
therefore:
{a, b} = Transpose[list];
Transpose[{a, Accumulate[b]}]
Also this will do the job:
Rest@FoldList[{#2[[1]], #1[[2]] + #2[[2]]} &, {0, 0}, list]
or even easier
list[[All,2]]=Accumulate@list[[All,2]]; list
thanks to Mike Honeychurch, without pure function:
list = {{a1, b1}, {a2, b2}, {a3, b3}};
Thread[{Thread[list][[1]], Rest@FoldList[Plus, 0, Thread[list][[2]]]}]
(* {{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}} *)
and shorter (one expression):
Thread[{list[[All, 1]], Accumulate[list][[All, 2]]}]
Rest@FoldList
structure works?
$\endgroup$
Rest
just removes first element in the list, i.e. Rest[{1, 2, 3}]
gives {2, 3}. @
is a shorthand for head application. So Rest@FoldList[...]
is the same as Rest[FoldList[...]]
. Finally, FoldList[Plus, 0, {a, b, c}]
gives {0, a, a + b, a + b + c}.
Now you may see why we need Rest
- just to get rid of 0
.
$\endgroup$
This is another way and an active effort to advertise the ThroughOperator
that was developed by @Sjoerd Smit.
To the extend of my knowledge it was first suggested in this answer
.
list = {{a1, b1}, {a2, b2}, {a3, b3}};
list[[All, 1]]
ResourceFunction["ThroughOperator"][{Accumulate}][
list[[All, 2]]] // Flatten
Thread[{%%, %}]
{{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}}
ThroughOperator
is very flexible, so I hope they consider it as an option in a future version. Nicely done, mate! :-)
$\endgroup$
Commented
Dec 31, 2023 at 1:21
Another implementation using FoldList
and MapAt
:
pairs = {{a1, b1}, {a2, b2}, {a3, b3}};
f = FoldList[Apply[Plus]@*Flatten@*List, Nothing, #] &;
By entering Nothing
instead of zero as the initial element in FoldList
, we avoid the need to use Rest
to remove the first element of the cumulative list. This choice makes the code cleaner and avoids the need to handle special cases.
Transpose@MapAt[f, Transpose@pairs, 2]
(*{{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}}*)
As the version proposed by @J. M.'s eventual burnout in a comment, but without using Accumulate
.
list = {{a1, b1}, {a2, b2}, {a3, b3}};
Using SubsetMap
(new in 12.0)
SubsetMap[Accumulate, list, {All, 2}]
{{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}}
list = {{a1, b1}, {a2, b2}, {a3, b3}};
Using ReplaceAt
(new in 13.1)
Transpose @ ReplaceAt[Transpose[list], x_ :> Accumulate[x], 2]
{{a1, b1}, {a2, b1 + b2}, {a3, b1 + b2 + b3}}
{as, bs} = Transpose[pairs]; result = Transpose[{as, Accumulate[bs]}]
$\endgroup$Transpose[MapAt[Accumulate, Transpose[pairs], 2]]
. $\endgroup$