# How to define function that can change patterns

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.

-

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

-