6
$\begingroup$

I have 32 columns of annual data in varying lengths which I can simulate as follows:

 SeedRandom[23458];
lengths = RandomInteger[{50, 100}, 32];
cols = RandomReal[{0, 1}, #] & /@ lengths;

From this I need successive accumulations of ten years. So I have two questions. First, how do I Join multiple years? There is surely something more elegant than this

    Join[cols[[1]], cols[[2]], cols[[3]], 
  cols[[4]](*...and so forth through cols[[10]]*)];

Second, how do I get a sequence which accumulates the first ten years, then years 2-11, then years 3-12, then years 4-13 and so forth through to years 23-32?

$\endgroup$
1
  • $\begingroup$ Instead of Join[cols[[1]], cols[[2]], cols[[3]],... you can just do Flatten[cols] $\endgroup$
    – Nasser
    Apr 15, 2022 at 4:19

5 Answers 5

8
$\begingroup$
SeedRandom[23458];
lengths = RandomInteger[{50, 100}, 32];
cols = RandomReal[{0, 1}, #] & /@ lengths;

This gives you the parts from 1-10, 2-11 ..

parts10 = Partition[cols, 10, 1]

The joined data is:

ts = Join @@@ parts10;

Within each of the joined lists:

acc1 = Table[Accumulate[ts[[i]] ], {i, 1, Length@ts}]
ListLinePlot[acc1]

enter image description here

Another variation could be:

acc2 = FoldList[Plus, #] & /@ ts;
acc1 == acc2

(* True *)

$\endgroup$
11
$\begingroup$

You can also use BlockMap:

blockaccumulated = BlockMap[Accumulate@*Apply[Join], cols, 10, 1];

ListLinePlot[blockaccumulated]

enter image description here

$\endgroup$
5
$\begingroup$
SeedRandom[23458];
lengths = RandomInteger[{50, 100}, 32];
cols = RandomReal[{0, 1}, #] & /@ lengths;

test1[ii1_, ii2_] := Join[Flatten@Table[cols[[i]], {i, ii1, ii2}]];

Testing this against the manual construction

test2 = Join[cols[[1]], cols[[2]], cols[[3]], cols[[4]], cols[[5]], 
   cols[[6]], cols[[7]], cols[[8]], cols[[9]], cols[[10]]];

LinearAlgebra`Private`ZeroArrayQ[test1[1, 10] - test2]

true

Not sure I understand what you meant when you said Accumulate, but if I am right, you can accumulate from year xx1 to xx2 like so:

accum[xx1_, xx2_] := 
 Accumulate[Flatten@Table[cols[[i]], {i, xx1, xx2}]]

From year 2 to 11

accum[2, 11]

accumulate

$\endgroup$
3
$\begingroup$

Overnight I came up with this, but some of the other suggestions are more efficient

rolling[data_List, n_] := Module[{series},
  series = Flatten[data[[n ;; n + 9]]];
  Length[series]
  ]
Table[rolling[data, i], {i, 1, 23}]

I appreciate the help

$\endgroup$
3
$\begingroup$

Over the years I've seen similar problems where you would think MovingMap[ ] would be the key to the solution, but it is super-awkward to use, so I made this simplified version that I use frequently.

simpleMovingMap[f_, data_, numInWindow_] := f /@ Partition[data, numInWindow, 1];

Applying to your problem, using much smaller data

SeedRandom[23458];
lengths = RandomInteger[{2, 3}, 10];
cols = RandomInteger[{0, 10}, #] & /@ lengths;

gives

{{3, 4}, 
{5, 5}, 
{5, 2, 7},
 {9, 2}, 
{4, 4}, 
{1, 3, 10}, 
{6, 5, 10},
 {8, 6, 0}, 
{4, 8, 5}, 
{0, 1, 9}}

Computing what you want, combining runs of 3 years instead of 10.

res = simpleMovingMap[Flatten, cols, 3];

\begin{array}{ccccccccc} 3 & 4 & 5 & 5 & 5 & 2 & 7 & \text{} & \text{} \\ 5 & 5 & 5 & 2 & 7 & 9 & 2 & \text{} & \text{} \\ 5 & 2 & 7 & 9 & 2 & 4 & 4 & \text{} & \text{} \\ 9 & 2 & 4 & 4 & 1 & 3 & 10 & \text{} & \text{} \\ 4 & 4 & 1 & 3 & 10 & 6 & 5 & 10 & \text{} \\ 1 & 3 & 10 & 6 & 5 & 10 & 8 & 6 & 0 \\ 6 & 5 & 10 & 8 & 6 & 0 & 4 & 8 & 5 \\ \end{array}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.