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$

3 Answers 3

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$
1
  • $\begingroup$ Thank you very much! $\endgroup$ Commented Oct 23, 2017 at 15:30
2
$\begingroup$
GroupBy[data, Part[First[#], ;; 2] &, Apply[Times, Last /@ #] &] 
$\endgroup$
1
  • $\begingroup$ Thanks so much! I knew I was overcomplicating things and that there was a much easier and quicker solution.... $\endgroup$ Commented Oct 17, 2017 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$
1
  • $\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$ Commented Oct 23, 2017 at 16:29

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.