## select, group and manipulate elements in list based on date ranges

1

Question from a beginner. I have data containing dates and values of the format:

    data = {{{2015, 1, 1}, 2}, {{2015, 1, 2}, 3}, {{2015, 2, 1}, 4}, {{2015, 2, 2}, 5}, {{2016, 1, 1}, 6}, {{2016, 1, 2}, 7}}


Aim is to multiply the values of each day in a month, e.g. for January 2015, the result should be 2*3=6, for February 2015 4*5=20 and so on. Ideally, the output would be a list of the format {{January 2015, 6}, {February 2015, 20},etc}, but just a list of the results of the multiplications would be fine.

To group the data by month, I use:

selectElements[list_, start_, end_] := Module[{s = AbsoluteTime@start,
e = AbsoluteTime@end},  Select[list, Composition[s <= # <= e &, AbsoluteTime, First]]]


I then create a table multiplying the values of the data grouped by month:

test1 = Table[Times @@ selectElements[data, {y, m, 1}, {y, m, 31}], {y, 2015, 2016}, {m, 1, 12}]


However, this multiplies not only the values, but also the dates themselves giving me:

    {{{{4060225, 1, 2}, 6}, {{4060225, 4, 2}, 20}, 1, 1, 1, 1, 1, 1, 1, 1,1, 1}, {{{4064256, 1, 1}, 42}, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}


I'm sure there is an easy way to get just the dates and the values I'm interested in (i.e. 6,20,42, ideally with month/year), but so far I couldn't find it. I'd be very grateful for any pointers.

2

I think this is a simpler variant of @Alan's answer:

GroupBy[
data,
Most@*First -> Last,
Apply[Times]
]


<|{2015, 1} -> 6, {2015, 2} -> 20, {2016, 1} -> 42|>

Thank you very much! – flux – 2017-10-23T15:30:57.710

2

GroupBy[data, Part[First[#], ;; 2] &, Apply[Times, Last /@ #] &]


Thanks so much!

I knew I was overcomplicating things and that there was a much easier and quicker solution.... – flux – 2017-10-17T16:11:31.340

0

TimeSeriesAggregate can also be used, e.g.:

#1[[1, {1, 2}]] -> #2 & @@@TimeSeriesAggregate[data, "Month", Times @@ # &]


yielding:

{{2015, 1} -> 6, {2015, 2} -> 20, {2016, 1} -> 42}


Hi, thanks for your suggestion re using TimeSeriesAggregate. However, when I'm running the exact code you suggest, I get:

Part specification 3630398400[[1,{1,2}]] is longer than depth of object.

{3630398400[[1, {1, 2}]] -> 6, 3632947200[[1, {1, 2}]] -> 20,


3661934400[[1, {1, 2}]] -> 42}

It's probably a matter of me not really understanding something quite basic in your answer... apologies in advance. – flux – 2017-10-23T16:29:18.713