Repository: alteryx/evalml
Pull request #4200 (2023-06-06 13:18:08)

update get_forecast_distance to handle gap
### Pull Request Description
Resolves https://github.com/alteryx/evalml/issues/4201

This updates `get_forecast_period` to account for the `gap` parameter, so we only show predictions for `X[-1] + gap` to `forecast_horizon`.

-----
*After creating the pull request: in order to pass the **release_notes_updated** check you will need to update the "Future Release" section of* `docs/source/release_notes.rst` *to include this pull request by adding :pr:`123`.*


machineFL: No linked issues found. Please add the corresponding issues in the pull request description. <br/> [Use GitHub automation to close the issue when a PR is merged](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) <!-- metadata = {"action":"linked_issue"} -->
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/alteryx/evalml/pull/4200?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=alteryx) Report
> Merging [#4200](https://app.codecov.io/gh/alteryx/evalml/pull/4200?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=alteryx) (50c9e98) into [main](https://app.codecov.io/gh/alteryx/evalml/commit/0be3c3c8aa78091f05de25380f59689c2e21b9ed?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=alteryx) (0be3c3c) will **decrease** coverage by `72.1%`.
> The diff coverage is `0.0%`.

```diff
@@           Coverage Diff            @@
##            main   #4200      +/-   ##
========================================
- Coverage   99.7%   27.6%   -72.1%     
========================================
  Files        349     349              
  Lines      38154   38154              
========================================
- Hits       38037   10511   -27526     
- Misses       117   27643   +27526     
```


| [Impacted Files](https://app.codecov.io/gh/alteryx/evalml/pull/4200?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=alteryx) | Coverage Δ | |
|---|---|---|
| [...valml/pipelines/time\_series\_regression\_pipeline.py](https://app.codecov.io/gh/alteryx/evalml/pull/4200?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=alteryx#diff-ZXZhbG1sL3BpcGVsaW5lcy90aW1lX3Nlcmllc19yZWdyZXNzaW9uX3BpcGVsaW5lLnB5) | `29.4% <ø> (-70.6%)` | :arrow_down: |
| [...peline\_tests/test\_time\_series\_baseline\_pipeline.py](https://app.codecov.io/gh/alteryx/evalml/pull/4200?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=alteryx#diff-ZXZhbG1sL3Rlc3RzL3BpcGVsaW5lX3Rlc3RzL3Rlc3RfdGltZV9zZXJpZXNfYmFzZWxpbmVfcGlwZWxpbmUucHk=) | `0.0% <0.0%> (-100.0%)` | :arrow_down: |

... and [277 files with indirect coverage changes](https://app.codecov.io/gh/alteryx/evalml/pull/4200/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=alteryx)



Patch:
diff --git a/docs/source/release_notes.rst b/docs/source/release_notes.rst
index c1f11d56..f171ae48 100644
--- a/docs/source/release_notes.rst
+++ b/docs/source/release_notes.rst
@@ -8,6 +8,7 @@ Release Notes
         * Added option to exclude time index in ``IDColumnsDataCheck`` :pr:`4194`
     * Fixes
         * Fixed small errors in ``ARIMARegressor`` implementation :pr:`4186`
+        * Fixed ``get_forecast_period`` to properly handle ``gap`` parameter :pr:`4200`
     * Changes
     * Documentation Changes
     * Testing Changes
diff --git a/evalml/pipelines/time_series_regression_pipeline.py b/evalml/pipelines/time_series_regression_pipeline.py
index 5490b2a4..93c4ec2a 100644
--- a/evalml/pipelines/time_series_regression_pipeline.py
+++ b/evalml/pipelines/time_series_regression_pipeline.py
@@ -114,7 +114,7 @@ class TimeSeriesRegressionPipeline(TimeSeriesPipelineBase):
             ValueError: If pipeline is not trained.
 
         Returns:
-            pd.Series: Datetime periods out to `forecast_horizon + gap`.
+            pd.Series: Datetime periods from `gap` to `forecast_horizon + gap`.
 
         Example:
             >>> X = pd.DataFrame({'date': pd.date_range(start='1-1-2022', periods=10, freq='D'), 'feature': range(10, 20)})
@@ -128,7 +128,7 @@ class TimeSeriesRegressionPipeline(TimeSeriesPipelineBase):
             >>> pipeline.fit(X, y)
             pipeline = TimeSeriesRegressionPipeline(component_graph={'Linear Regressor': ['Linear Regressor', 'X', 'y']}, parameters={'Linear Regressor':{'fit_intercept': True, 'n_jobs': -1}, 'pipeline':{'gap': 1, 'max_delay': 1, 'forecast_horizon': 2, 'time_index': 'date'}}, random_seed=0)
             >>> dates = pipeline.get_forecast_period(X)
-            >>> expected = pd.Series(pd.date_range(start='2022-01-11', periods=(gap + forecast_horizon), freq='D'), name='date', index=[10, 11, 12])
+            >>> expected = pd.Series(pd.date_range(start='2022-01-11', periods=forecast_horizon, freq='D').shift(gap), name='date', index=[10, 11])
             >>> assert dates.equals(expected)
         """
         if not self._is_fitted:
@@ -142,10 +142,9 @@ class TimeSeriesRegressionPipeline(TimeSeriesPipelineBase):
             pd.date_range(
                 start=first_date,
                 periods=self.forecast_horizon
-                + self.gap
                 + 1,  # Add additional period to account for dropping first date row
                 freq=self.frequency,
-            ),
+            ).shift(self.gap),
         )
 
         # Generate numerical index
@@ -165,7 +164,7 @@ class TimeSeriesRegressionPipeline(TimeSeriesPipelineBase):
             y (pd.Series, np.ndarray): Targets used to train the pipeline of shape [n_samples_train].
 
         Returns:
-            Predictions out to `forecast_horizon + gap` periods.
+            Predictions from `gap` periods out to `forecast_horizon + gap` periods.
         """
         X, y = self._convert_to_woodwork(X, y)
         pred_dates = pd.DataFrame(self.get_forecast_period(X))


Test patch:
diff --git a/evalml/tests/pipeline_tests/test_time_series_baseline_pipeline.py b/evalml/tests/pipeline_tests/test_time_series_baseline_pipeline.py
index f0d0c60e..20a5f4ed 100644
--- a/evalml/tests/pipeline_tests/test_time_series_baseline_pipeline.py
+++ b/evalml/tests/pipeline_tests/test_time_series_baseline_pipeline.py
@@ -107,9 +107,9 @@ def test_time_series_get_forecast_period(forecast_horizon, gap, numeric_idx, ts_
     clf.fit(X, y)
     result = clf.get_forecast_period(X)
 
-    assert result.size == forecast_horizon + gap
-    assert all(result.index == range(len(X), len(X) + forecast_horizon + gap))
-    assert result.iloc[0] == X.iloc[-1]["date"] + np.timedelta64(1, clf.frequency)
+    assert result.size == forecast_horizon
+    assert all(result.index == range(len(X), len(X) + forecast_horizon))
+    assert result.iloc[0] == X.iloc[-1]["date"] + np.timedelta64(1 + gap, clf.frequency)
     assert np.issubdtype(result.dtype, np.datetime64)
     assert result.name == "date"
 
@@ -119,7 +119,7 @@ def test_time_series_get_forecast_predictions(forecast_horizon, gap, ts_data):
     X, _, y = ts_data(problem_type=ProblemTypes.TIME_SERIES_REGRESSION)
 
     X_train, y_train = X.iloc[:15], y.iloc[:15]
-    X_validation = X.iloc[15 : (15 + gap + forecast_horizon)]
+    X_validation = X.iloc[15 + gap : (15 + gap + forecast_horizon)]
 
     clf = TimeSeriesRegressionPipeline(
         component_graph={
@@ -166,5 +166,4 @@ def test_time_series_get_forecast_predictions(forecast_horizon, gap, ts_data):
     clf.fit(X_train, y_train)
     forecast_preds = clf.get_forecast_predictions(X=X_train, y=y_train)
     X_val_preds = clf.predict(X_validation, X_train=X_train, y_train=y_train)
-
     assert_series_equal(forecast_preds, X_val_preds)