9

Given time series data as follows:

data = 
  {{{2011, 1, 13}, 10}, {{2011, 2, 14}, 17}, {{2011, 3, 15}, 20}, 
   {{2012, 1, 16}, 30}, {{2012, 2, 17}, 40}};

Evaluating

Cases[data, {{year_, month_, day_}, val_} /; year == 2011] 

will return the data that are in year 2011.

Are there any ways that I can define a function that can change the criteria of matching patterns?

For example,

TimeSelection[data_, pattern_] := Cases[data, {{year_, month_, day_}, val_} /; pattern]  

If the pattern is month == 2, the return will only be the data in February.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
Dia
  • 93
  • 3

1 Answers1

10

Your function would/should work, except for the fact that automatic renaming is taking place due to nested scoping constructs (here SetDelayed and Condition). Essentially Mathematica is trying to prevent a name collision, but that (shared names) is exactly what you need here. You can see the problem using Trace:

TimeSelection[{"anything"}, month == 2] // Trace
{TimeSelection[{anything},month==2],Cases[{anything},
  {{year$_,month$_,day$_},val$_}/;month==2],{}}

Note that the pattern name month has been renamed to month$. One simple work-around therefore is to use month$ in your condition:

TimeSelection[data, month$ == 2]
{{{2011, 2, 14}, 17}, {{2012, 2, 17}, 40}}

Another, more robust method, is to assemble the Condition expression at evaluation so your Pattern names do not explicitly appear inside that head as visible to SetDelayed:

TimeSelection[data_, pattern_] := 
  Cases[data, # /; pattern] & @ {{year_, month_, day_}, val_}

TimeSelection[data, month == 2]
{{{2011, 2, 14}, 17}, {{2012, 2, 17}, 40}}

The mechanism of this and other work-arounds is discussed in the post linked at the top of this answer. (Function with Slot does not suffer from automatic renaming, but Function with named parameters does.)

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371