Add a new CustomDateFeatureSet class to calculate holiday features ba… (#12)

* Add a new CustomDateFeatureSet class to calculate holiday features based on an array of pandas timestamps

Add a new CustomDateFeatureSet class to calculate holiday features based on an array of pandas timestamps

* Added test case for the CustomDateFeatureSet

Added test case for the CustomDateFeatureSet

* Added new class in the init file

Added new class in the init file
This commit is contained in:
Edrin Basha
2020-05-22 15:43:13 +02:00
committed by Kashif Rasul
parent e5f66530b1
commit 204efc8bdc
3 changed files with 93 additions and 1 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
from .holiday import SPECIAL_DATE_FEATURES, SpecialDateFeatureSet
from .holiday import SPECIAL_DATE_FEATURES, SpecialDateFeatureSet, CustomDateFeatureSet
from .lag import get_lags_for_frequency, get_fourier_lags_for_frequency
from .time_feature import (
DayOfMonth,
+74
View File
@@ -219,3 +219,77 @@ class SpecialDateFeatureSet:
for feat_name in self.feature_names
]
)
class CustomDateFeatureSet:
"""
Implements calculation of holiday features. The CustomDateFeatureSet is
applied on a pandas Series with Datetimeindex and returns a 2D array of
the shape (len(dates), num_features), where num_features are the number
of holidays.
Note that for lower than daily granularity the distance to the holiday is
still computed on a per-day basis.
Example use:
>>> import pandas as pd
>>> cfs = CustomDateFeatureSet([pd.to_datetime('20191129', format='%Y%m%d'), pd.to_datetime('20200101', format='%Y%m%d')], kernel)
>>> date_indices = pd.date_range(
... start="2019-11-24",
... end="2019-12-31",
... freq='D'
... )
>>> cfs(date_indices)
array([[1., 0., 0., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0., 0., 0.]])
Example use for using a squared exponential kernel:
>>> kernel = squared_exponential_kernel(alpha=1.0)
>>> cfs = CustomDateFeatureSet([pd.to_datetime('20191129', format='%Y%m%d'), pd.to_datetime('20200101', format='%Y%m%d')], kernel)
>>> cfs(date_indices)
array([[1.00000000e+00, 3.67879441e-01, 1.83156389e-02, 1.23409804e-04,
1.12535175e-07, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[3.67879441e-01, 1.00000000e+00, 3.67879441e-01, 1.83156389e-02,
1.23409804e-04, 1.12535175e-07, 0.00000000e+00, 0.00000000e+00]])
"""
def __init__(
self,
reference_dates: List[pd.Timestamp],
kernel_function: Callable[[int], int] = indicator,
):
"""
Parameters
----------
reference_dates
list of panda timestamps for which features should be created.
kernel_function
kernel function to pass the feature value based
on distance in days. Can be indicator function (default),
exponential_kernel, squared_exponential_kernel or user defined.
"""
self.reference_dates = reference_dates
self.kernel_function = kernel_function
def __call__(self, dates):
"""
Transform a pandas series with timestamps to holiday features.
Parameters
----------
dates
Pandas series with Datetimeindex timestamps.
"""
return np.vstack(
[
np.hstack(
[
self.kernel_function((index - ref_date).days)
for index in dates
]
)
for ref_date in self.reference_dates
]
)
+18
View File
@@ -39,6 +39,7 @@ from pts.feature.holiday import (
CYBER_MONDAY,
SpecialDateFeatureSet,
squared_exponential_kernel,
CustomDateFeatureSet
)
test_dates = {
@@ -253,4 +254,21 @@ def test_special_date_feature_set_daily_squared_exponential():
sfs = SpecialDateFeatureSet([CHRISTMAS_EVE, CHRISTMAS_DAY], squared_exp_kernel)
computed_features = sfs(date_indices)
np.testing.assert_almost_equal(computed_features, reference_features, decimal=6)
def test_custom_date_feature_set():
ref_dates = [pd.to_datetime('20191129', format='%Y%m%d'), pd.to_datetime('20200101', format='%Y%m%d')]
kernel = exponential_kernel(alpha=1.0)
cfs = CustomDateFeatureSet(ref_dates, kernel)
sfs = SpecialDateFeatureSet([BLACK_FRIDAY, NEW_YEARS_DAY], kernel)
date_indices = pd.date_range(
start=pd.to_datetime('20191101', format='%Y%m%d'),
end=pd.to_datetime('20200131', format='%Y%m%d'),
freq='D')
assert(np.sum(cfs(date_indices) - sfs(date_indices)) == 0), "Features don't match"