Creating features from legacy feature specifications#

Users of timeseriesflattener version 1 should not have to rewrite all their feature specifications, so we have written a simple legacy API! It works for PredictorGroupSpecs, since those were the ones we had by far the most of.

Say you have a legacy specification defined like this:

from __future__ import annotations

import pandas as pd
from timeseriesflattener.v1.aggregation_fns import (
    change_per_day,
    count,
    earliest,
    latest,
    maximum,
    mean,
    minimum,
    summed,
    variance,
)
from timeseriesflattener.v1.feature_specs.group_specs import NamedDataframe, PredictorGroupSpec
from timeseriesflattener.v1.feature_specs.single_specs import PredictorSpec as Version1PredictorSpec

legacy_spec = PredictorGroupSpec(
    lookbehind_days=((1, 2), (3, 4)),
    named_dataframes=[
        NamedDataframe(
            df=pd.DataFrame({"timestamp": ["2013-01-01"], "dw_ek_borger": "1", "value": 1}),
            name="test",
        ),
        NamedDataframe(
            df=pd.DataFrame({"timestamp": ["2013-01-01"], "dw_ek_borger": "2", "value": 2}),
            name="test2",
        ),
    ],
    aggregation_fns=[
        latest,
        earliest,
        maximum,
        minimum,
        mean,
        summed,
        count,
        variance,
        # boolean, requires the fallback to be a bool
        change_per_day,
    ],
    fallback=[0],
).create_combinations()

print(f"The generated specs are for version 1: {isinstance(legacy_spec[0], Version1PredictorSpec)}")
The generated specs are for version 1: True

If you want the output feature specifications to be compatible with version 2, all you have to do is replace the PredictorGroupSpec import:

from timeseriesflattener import PredictorSpec as Version2PredictorSpec

# IMPORT CHANGED BELOW #
# from timeseriesflattener.v1.feature_specs.single_specs import PredictorSpec as Version1PredictorSpec # noqa: ERA001
from timeseriesflattener.specs.from_legacy import PredictorGroupSpec

# IMPORT CHANGED ABOVE #

new_specs = PredictorGroupSpec(
    lookbehind_days=((1, 2), (3, 4)),
    named_dataframes=[
        NamedDataframe(
            df=pd.DataFrame({"timestamp": ["2013-01-01"], "dw_ek_borger": "1", "value": 1}),
            name="test",
        ),
        NamedDataframe(
            df=pd.DataFrame({"timestamp": ["2013-01-01"], "dw_ek_borger": "2", "value": 2}),
            name="test2",
        ),
    ],
    aggregation_fns=[
        latest,
        earliest,
        maximum,
        minimum,
        mean,
        summed,
        count,
        variance,
        # boolean, requires the fallback to be a bool
        change_per_day,
    ],
    fallback=[0],
).create_combinations()

print(f"The generated specs are for version 2: {isinstance(new_specs[0], Version2PredictorSpec)}")
The generated specs are for version 2: True

And then you get specifications that are ready to be aggregated by version 2!