This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch tdd/issue-21734-prophet-uncertainty-negative
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to 
refs/heads/tdd/issue-21734-prophet-uncertainty-negative by this push:
     new 51728d0aca3 test(prophet): pin yhat_lower can be negative for negative 
series
51728d0aca3 is described below

commit 51728d0aca3ebc5d37ab3798548579794dd837c5
Author: Claude Code <[email protected]>
AuthorDate: Thu May 14 18:42:48 2026 -0700

    test(prophet): pin yhat_lower can be negative for negative series
    
    Closes #21734
    
    Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 .../pandas_postprocessing/test_prophet.py          | 109 +++++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/tests/unit_tests/pandas_postprocessing/test_prophet.py 
b/tests/unit_tests/pandas_postprocessing/test_prophet.py
index c21dbb0d82b..193b70c4038 100644
--- a/tests/unit_tests/pandas_postprocessing/test_prophet.py
+++ b/tests/unit_tests/pandas_postprocessing/test_prophet.py
@@ -184,3 +184,112 @@ def test_prophet_incorrect_time_grain():
             periods=10,
             confidence_interval=0.8,
         )
+
+
+def test_prophet_uncertainty_lower_bound_can_be_negative_for_negative_series():
+    """
+    Regression for #21734: when the input series contains negative values,
+    the forecast's lower confidence bound (``__yhat_lower``) must be allowed
+    to go below zero. The original bug claimed Superset clipped the lower
+    bound at 0, hiding the natural shape of the uncertainty interval for
+    series like temperatures or signed deltas.
+
+    Superset's wrapper passes through Prophet's output unchanged (no
+    clipping in ``superset/utils/pandas_postprocessing/prophet.py``); this
+    test pins that contract end-to-end. If a future refactor introduces
+    a ``max(0, lower)`` clamp, this test fails immediately.
+    """
+    if find_spec("prophet") is None:
+        pytest.skip("prophet not installed")
+
+    # All-negative monthly series — any reasonable forecast must predict
+    # negative values (and therefore negative uncertainty bounds) too.
+    negative_df = pd.DataFrame(
+        {
+            DTTM_ALIAS: [datetime(2020, m, 1) for m in range(1, 13)]
+            + [datetime(2021, m, 1) for m in range(1, 13)],
+            "temperature": [
+                -5.0,
+                -7.0,
+                -3.0,
+                1.0,
+                8.0,
+                14.0,
+                17.0,
+                16.0,
+                11.0,
+                5.0,
+                -1.0,
+                -4.0,
+                -6.0,
+                -8.0,
+                -2.0,
+                2.0,
+                9.0,
+                15.0,
+                18.0,
+                17.0,
+                12.0,
+                6.0,
+                0.0,
+                -3.0,
+            ],
+        }
+    )
+
+    result = prophet(
+        df=negative_df,
+        time_grain="P1M",
+        periods=3,
+        confidence_interval=0.9,
+    )
+
+    assert "temperature__yhat_lower" in result.columns
+    # At least one forecast point's lower bound must be negative for a
+    # series whose actuals span both signs. A clamp at zero would force
+    # this assertion to fail.
+    assert (result["temperature__yhat_lower"] < 0).any(), (
+        "Forecast lower bound was non-negative everywhere despite a "
+        "series with negative actuals — suggests an unexpected clamp at "
+        "zero was reintroduced (regression of #21734)."
+    )
+
+
+def test_prophet_does_not_clamp_yhat_below_zero_for_negative_actuals():
+    """
+    Companion to the lower-bound test above: the central forecast
+    (``__yhat``) must also be allowed to go negative.
+    A bug that clamps the central forecast at zero would force the lower
+    bound non-negative as a side effect, masking the wider issue.
+    """
+    if find_spec("prophet") is None:
+        pytest.skip("prophet not installed")
+
+    negative_df = pd.DataFrame(
+        {
+            DTTM_ALIAS: [datetime(2020, m, 1) for m in range(1, 13)],
+            "balance": [
+                -100.0,
+                -110.0,
+                -95.0,
+                -120.0,
+                -130.0,
+                -125.0,
+                -140.0,
+                -135.0,
+                -150.0,
+                -145.0,
+                -160.0,
+                -155.0,
+            ],
+        }
+    )
+
+    result = prophet(
+        df=negative_df,
+        time_grain="P1M",
+        periods=2,
+        confidence_interval=0.8,
+    )
+
+    assert (result["balance__yhat"] < 0).any()

Reply via email to