Skip to content

Commit 3715a96

Browse files
committed
fix(models): pad predictions to match index length in prepare_prediction_models
Fix a bug in `prepare_prediction_models` where model outputs could mismatch the expected index length when the available data is smaller than the configured moving average window size. Instead of slicing and risking index errors, predictions are now aligned to the reference index by right-aligning predictions and padding missing entries with NaNs if necessary. This makes the model preparation robust even with minimal data and prevents silent failures or incorrect series construction. Signed-off-by: cyiallou - Costas <[email protected]>
1 parent e3e688b commit 3715a96

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@
1414
## Bug Fixes
1515

1616
* Fixed a bug where the Solar Maintenance app would crash if some requested inverter components were missing from the reporting data. Missing components are now handled gracefully with a warning.
17+
* Fixed a bug in prediction model preparation where predictions could fail or mismatch the expected index when using minimal data and a large moving average window. Predictions are now correctly aligned with the data index, with missing values padded with NaN.

src/frequenz/lib/notebooks/solar/maintenance/models.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -145,15 +145,7 @@ def prepare_prediction_models(
145145
predictions = model_function(data=data_to_use, **model_params)
146146

147147
if not isinstance(predictions, pd.Series):
148-
if len(data_to_use) - len(predictions) > 0:
149-
tmp_series = pd.Series(data=np.nan, index=data_to_use.index)
150-
tmp_series.iloc[-len(predictions) :] = predictions
151-
predictions = tmp_series
152-
else:
153-
predictions = pd.Series(
154-
data=predictions, index=data_to_use.index[-len(predictions) :]
155-
)
156-
predictions.name = "predictions"
148+
predictions = _align_predictions_to_index(predictions, data_to_use.index)
157149

158150
prediction_models[label] = {"predictions": predictions}
159151

@@ -558,3 +550,34 @@ def _get_pvgis_hourly(
558550
predictions: SeriesFloat = simulation_data["power_W"]
559551
predictions.name = "predictions"
560552
return predictions
553+
554+
555+
def _align_predictions_to_index(
556+
predictions: NDArray[np.float64],
557+
reference_index: pd.Index[Any],
558+
) -> SeriesFloat:
559+
"""Align predictions to a reference index, padding with NaNs if necessary.
560+
561+
Args:
562+
predictions: The prediction outputs.
563+
reference_index: The DataFrame index to align to.
564+
565+
Returns:
566+
A pandas Series with predictions aligned to the reference index.
567+
568+
Note:
569+
If predictions are longer than the reference index, predictions will
570+
be truncated from the left. If predictions are shorter, they are
571+
right-aligned and earlier entries are filled with NaN.
572+
"""
573+
reference_length = len(reference_index)
574+
prediction_length = len(predictions)
575+
576+
if prediction_length > reference_length:
577+
predictions = predictions[-reference_length:]
578+
elif prediction_length < reference_length:
579+
padded_predictions = np.full(reference_length, np.nan, dtype=np.float64)
580+
padded_predictions[-prediction_length:] = predictions
581+
predictions = padded_predictions
582+
583+
return pd.Series(data=predictions, index=reference_index, name="predictions")

0 commit comments

Comments
 (0)