1
$\begingroup$

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.

$\endgroup$
2
$\begingroup$

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|>

$\endgroup$
  • $\begingroup$ Thank you very much! $\endgroup$ – flux Oct 23 '17 at 15:30
2
$\begingroup$
GroupBy[data, Part[First[#], ;; 2] &, Apply[Times, Last /@ #] &]
$\endgroup$
  • $\begingroup$ Thanks so much! I knew I was overcomplicating things and that there was a much easier and quicker solution.... $\endgroup$ – flux Oct 17 '17 at 16:11
0
$\begingroup$

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}
$\endgroup$
  • $\begingroup$ 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. $\endgroup$ – flux Oct 23 '17 at 16:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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