4
$\begingroup$

Hopefully this is an easy question but I couldn't find an easy answer anyway. Surely there is some simple way to splice this...

I want to take a large datelist in the format of {{2014,12,31}, value} and extract only the first date of every year. Here is the code that generates a date list:

sampleDates = Thread[
   {DateRange[{2010, 1, 1}, {2014, 12, 31}], 
    RandomFunction[RandomWalkProcess[0.5], {1825}]["Values"]}
   ];
DateListPlot[sampleDates]

How can I obtain a list which is just

{ {2010,1,1}, 0}, {2011,1,1}, 10}, {2012,1,1}, 23} ... }

from the sampleDates set above?

$\endgroup$
7
$\begingroup$

I like to try to use the new TimeSeries functionality when possible. This works by first rescaling the time range to use actual dates rather than integer time stamps and then picks out only those dates we are interested in.

data = RandomFunction[RandomWalkProcess[0.5], {1825}];
ts = TimeSeriesRescale[data, {{2010, 1, 1}, {2014, 12, 31}, "Day"}];
jan1 = TimeSeriesResample[ts, {{2010, 1, 1}, {2014, 12, 31}, "Year"}];

DateListPlot[{ts, jan1}, Joined -> {True, False}, 
    PlotStyle -> {Automatic, {Red, PointSize[.025], Opacity[.5]}}]

enter image description here

Note that you could use the explicit list of dates rather than the {tmin, tmax, dt} specification when resampling but I find this more concise in this particular case.

| improve this answer | |
$\endgroup$
5
$\begingroup$
newyearF = Pick[#,{##2}=={1,1}&@@@#[[All,1]]]&;


sampleDates = Thread[
   {DateRange[{2010, 1, 1}, {2014, 12, 31}], 
    RandomFunction[RandomWalkProcess[0.5], {1825}]["Values"]}
   ];

newyearF @ sampleDates
(* {{{2010,1,1},0}, {{2011,1,1},-1}, {{2012,1,1},-20}, {{2013,1,1},-48}, {{2014,1,1},-11}} *)

To see the selected dates in DateListPlot, you can use

DateListPlot[{sampleDates,newyearF@sampleDates},
             Joined->{True,False},
             PlotStyle->{Automatic,Directive[{PointSize[Large],Red}]},
             GridLines->{newyearF[sampleDates][[All,1]],None}]

or

DateListPlot[sampleDates,
             GridLines->{newyearF[sampleDates][[All,1]],None},
             Mesh->{AbsoluteTime/@newyearF[sampleDates][[All,1]]},
             MeshStyle->Directive[{PointSize[Large],Red}]]

enter image description here

Update: The function TimeSeriesResample used in Andy's answer is not available for version 9. An alternative is to use the functions TemporalData and TemporalData`Resample:

tdResample = TemporalData`Resample;

dates = {{2010, 1, 1}, {2015, 1, 1}};
times = {DateRange @@ dates};
data = RandomFunction[RandomWalkProcess[0.5], {DateDifference @@ dates}];
td = TemporalData[data["States"], times];
td2 = tdResample[td, {1, "Year"}];

DateListPlot[{td["Path"], td2["Path"]}, Joined -> {True, False}, 
           PlotStyle -> {Automatic, Directive[PointSize[Large], Red]}] 

enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ This plot is super cool. Thanks for doing the extra work! $\endgroup$ – Tom Hayden Dec 31 '14 at 22:32
  • $\begingroup$ @Tom, my pleasure. Happy new year.. $\endgroup$ – kglr Dec 31 '14 at 22:36
  • $\begingroup$ @TomHayden Are neither solutions worthy of your acceptance? $\endgroup$ – David G. Stork Dec 31 '14 at 23:02
  • $\begingroup$ Oops, sorry for the delay there, guys! Thanks for these awesome answers. I picked the time series one because it's the most familiar tool that I know.. but I guess all of these are right. Mathematica SE is the best. $\endgroup$ – Tom Hayden Jan 2 '15 at 1:40
3
$\begingroup$
Select[sampleDates, #[[1, 2]] == #[[1, 3]] == 1 &]
| improve this answer | |
$\endgroup$
0
$\begingroup$

I think you can use a simple pattern match i.e

Cases[sampleDates, {{_, 1, 1}, _}, 2]
| improve this answer | |
$\endgroup$

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.