(df, test_periods=6)
| 368 | return cluster_labels.astype(str) |
| 369 | |
| 370 | def gen_real_pred_errors(df, test_periods=6): |
| 371 | errors = [] |
| 372 | for region in df['REGIONAL_OFFICE_NAME'].unique(): |
| 373 | region_data = df[df['REGIONAL_OFFICE_NAME'] == region] |
| 374 | for bnf_code in region_data['BNF_CHAPTER_PLUS_CODE'].unique(): |
| 375 | bnf_data = region_data[region_data['BNF_CHAPTER_PLUS_CODE'] == bnf_code] |
| 376 | ts_data = bnf_data.groupby('YEAR_MONTH')['TOTAL_COST'].sum().reset_index() |
| 377 | if len(ts_data) < test_periods + 3: |
| 378 | continue |
| 379 | train = ts_data.iloc[:-test_periods] |
| 380 | test = ts_data.iloc[-test_periods:] |
| 381 | try: |
| 382 | forecast_df = train_arima(train, test_periods) |
| 383 | if len(forecast_df) != len(test): |
| 384 | continue |
| 385 | y_true = test['TOTAL_COST'].values |
| 386 | y_pred = forecast_df['FORECAST'].values |
| 387 | mae = np.mean(np.abs(y_true - y_pred)) |
| 388 | bias = np.mean(y_pred - y_true) |
| 389 | mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100 if np.all(y_true != 0) else np.nan |
| 390 | errors.append({ |
| 391 | 'REGIONAL_OFFICE_NAME': region, |
| 392 | 'BNF_CATEGORY': bnf_code.split(':')[0].strip(), |
| 393 | 'Mean_Actual': np.mean(y_true), |
| 394 | 'MAE': mae, |
| 395 | 'Bias': bias, |
| 396 | 'MAPE': mape |
| 397 | }) |
| 398 | except Exception: |
| 399 | continue |
| 400 | return pd.DataFrame(errors) |
no test coverage detected