mmmapms commited on
Commit
ca0370b
·
verified ·
1 Parent(s): 59cc769

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -57
app.py CHANGED
@@ -289,40 +289,50 @@ elif section == 'Forecasts Quality':
289
 
290
  # Time series for last 1 week
291
  last_week = data.loc[data.index >= (data.index[-1] - pd.Timedelta(days=7))]
292
- st.write('The below plots show the time series of forecasts vs. observations provided by the ENTSO-E Transparency platform from the past week.')
293
-
294
- num_per_var=2
295
-
296
- forecast_columns_line=forecast_columns
 
 
 
 
 
 
 
297
 
298
- for i in range(0, len(forecast_columns_line), num_per_var):
299
- actual_col = forecast_columns_line[i]
300
- forecast_col = forecast_columns_line[i + 1]
301
 
302
- if forecast_col in data.columns:
303
- fig = go.Figure()
304
- fig.add_trace(go.Scatter(x=last_week.index, y=last_week[actual_col], mode='lines', name='Actual'))
305
- fig.add_trace(go.Scatter(x=last_week.index, y=last_week[forecast_col], mode='lines', name='Forecast ENTSO-E'))
306
- fig.update_layout(title=f'Forecasts vs Actual for {actual_col}', xaxis_title='Date', yaxis_title='Value [MW]')
307
-
308
- st.plotly_chart(fig)
309
 
 
310
 
311
  # Scatter plots for error distribution
312
  st.subheader('Error Distribution')
313
  st.write('The below scatter plots show the error distribution of all three fields: Solar, Wind and Load between the selected date range')
314
- data_2024 = data[data.index.year > 2023]
315
- for i in range(0, len(forecast_columns), 2):
316
- actual_col = forecast_columns[i]
317
- forecast_col = forecast_columns[i + 1]
318
- if forecast_col in data_2024.columns:
319
- obs = data_2024[actual_col]
320
- pred = data_2024[forecast_col]
321
- error = pred - obs
322
 
323
- fig = px.scatter(x=obs, y=pred, labels={'x': 'Observed [MW]', 'y': 'Predicted by ENTSO-E [MW]'})
324
- fig.update_layout(title=f'Error Distribution for {forecast_col}')
325
- st.plotly_chart(fig)
 
 
 
 
 
 
 
 
 
326
 
327
 
328
 
@@ -358,50 +368,83 @@ elif section == 'Forecasts Quality':
358
  accuracy_metrics.sort_values(by=accuracy_metrics.columns[1], ascending=True, inplace=True)
359
  accuracy_metrics = accuracy_metrics.round(4)
360
 
361
- col1, col2 = st.columns([3, 2])
362
 
363
  with col1:
 
 
 
 
 
 
 
 
 
 
364
  st.dataframe(accuracy_metrics)
365
-
366
- with col2:
367
- st.markdown("""
368
  <style>
369
- .big-font {
370
- font-size: 20px;
371
- font-weight: 500;
372
  }
373
  </style>
374
- <div class="big-font">
375
- Equations
376
- </div>
377
- """, unsafe_allow_html=True)
378
 
379
- st.markdown(r"""
380
- $\text{MAE} = \frac{1}{n}\sum_{i=1}^{n}|y_i - \hat{y}_i|$
381
 
382
-
383
- $\text{rMAE} = \frac{\text{MAE}}{MAE_{\text{Persistence Model}}}$
384
-
385
- """)
386
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
  st.subheader('ACF plots of Errors')
389
  st.write('The below plots show the ACF (Auto-Correlation Function) for the errors of all three data fields obtained from ENTSO-E: Solar, Wind and Load.')
390
 
391
- for i in range(0, len(forecast_columns), 2):
392
- actual_col = forecast_columns[i]
393
- forecast_col = forecast_columns[i + 1]
394
- if forecast_col in data.columns:
395
- obs = data[actual_col]
396
- pred = data[forecast_col]
397
- error = pred - obs
 
 
 
 
398
 
399
- st.write(f"**ACF of Errors for {actual_col}**")
400
- fig, ax = plt.subplots(figsize=(10, 5))
401
- plot_acf(error.dropna(), ax=ax)
402
- st.pyplot(fig)
403
 
404
- acf_values = acf(error.dropna(), nlags=240)
 
405
 
406
  # Section 3: Insights
407
  elif section == 'Insights':
@@ -427,6 +470,20 @@ elif section == 'Insights':
427
  st.pyplot(pairplot_fig)
428
 
429
  elif selected_country == 'Overall':
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
  st.subheader("Net Load Error Map")
431
  st.write("""
432
  The net load error map highlights the error in the forecasted versus actual net load for each country.
@@ -440,7 +497,7 @@ elif selected_country == 'Overall':
440
  filter_df = df[forecast_columns].dropna()
441
  net_load = filter_df['Load_entsoe'] - filter_df['Wind_onshore_entsoe'] - filter_df['Wind_offshore_entsoe'] - filter_df['Solar_entsoe']
442
  net_load_forecast = filter_df['Load_forecast_entsoe'] - filter_df['Wind_onshore_forecast_entsoe'] - filter_df['Wind_offshore_forecast_entsoe'] - filter_df['Solar_forecast_entsoe']
443
- error = (net_load - net_load_forecast).iloc[-1]
444
  date = filter_df.index[-1].strftime("%Y-%m-%d %H:%M") # Get the latest date in string format
445
  return error, date
446
 
@@ -514,6 +571,7 @@ elif selected_country == 'Overall':
514
 
515
  # Call the function to plot the map
516
  plot_net_load_error_map(data_dict)
 
517
 
518
  st.subheader("rMAE of Forecasts published on ENTSO-E TP")
519
  st.write("""
 
289
 
290
  # Time series for last 1 week
291
  last_week = data.loc[data.index >= (data.index[-1] - pd.Timedelta(days=7))]
292
+ st.write('The below plot shows the time series of forecasts vs. observations provided by the ENTSO-E Transparency platform from the past week.')
293
+
294
+ # Options for selecting the data to display
295
+ variable_options = {
296
+ "Load": ("Load_entsoe", "Load_forecast_entsoe"),
297
+ "Solar": ("Solar_entsoe", "Solar_forecast_entsoe"),
298
+ "Wind Onshore": ("Wind_onshore_entsoe", "Wind_onshore_forecast_entsoe"),
299
+ "Wind Offshore": ("Wind_offshore_entsoe", "Wind_offshore_forecast_entsoe")
300
+ }
301
+
302
+ # Dropdown to select the variable
303
+ selected_variable = st.selectbox("Select Variable for Line PLot", list(variable_options.keys()))
304
 
305
+ # Get the corresponding columns for the selected variable
306
+ actual_col, forecast_col = variable_options[selected_variable]
 
307
 
308
+ # Plot only the selected variable's data
309
+ fig = go.Figure()
310
+ fig.add_trace(go.Scatter(x=last_week.index, y=last_week[actual_col], mode='lines', name='Actual'))
311
+ fig.add_trace(go.Scatter(x=last_week.index, y=last_week[forecast_col], mode='lines', name='Forecast ENTSO-E'))
312
+ fig.update_layout(title=f'Forecasts vs Actual for {selected_variable}', xaxis_title='Date', yaxis_title='Value [MW]')
 
 
313
 
314
+ st.plotly_chart(fig)
315
 
316
  # Scatter plots for error distribution
317
  st.subheader('Error Distribution')
318
  st.write('The below scatter plots show the error distribution of all three fields: Solar, Wind and Load between the selected date range')
319
+ selected_variable = st.selectbox("Select Variable for Error Distribution", list(variable_options.keys()))
320
+
321
+ # Get the corresponding columns for the selected variable
322
+ actual_col, forecast_col = variable_options[selected_variable]
 
 
 
 
323
 
324
+ # Filter data for the selected year and check if columns are available
325
+ data_2024 = data[data.index.year > 2023]
326
+ if forecast_col in data_2024.columns:
327
+ obs = data_2024[actual_col]
328
+ pred = data_2024[forecast_col]
329
+
330
+ # Calculate error and plot
331
+ error = pred - obs
332
+ fig = px.scatter(x=obs, y=error, labels={'x': 'Observed [MW]', 'y': 'Error of Forecast ENTSO-E [MW]'})
333
+ fig.update_layout(title=f'Error Distribution for {selected_variable}')
334
+
335
+ st.plotly_chart(fig)
336
 
337
 
338
 
 
368
  accuracy_metrics.sort_values(by=accuracy_metrics.columns[1], ascending=True, inplace=True)
369
  accuracy_metrics = accuracy_metrics.round(4)
370
 
371
+ col1, col2 = st.columns([1, 2])
372
 
373
  with col1:
374
+ st.markdown(
375
+ """
376
+ <style>
377
+ .small-chart {
378
+ margin-top: 30px; /* Adjust this value as needed */
379
+ }
380
+ </style>
381
+ """,
382
+ unsafe_allow_html=True
383
+ )
384
  st.dataframe(accuracy_metrics)
385
+ st.markdown(
386
+ """
 
387
  <style>
388
+ .small-chart {
389
+ margin-top: -30px; /* Adjust this value as needed */
 
390
  }
391
  </style>
392
+ """,
393
+ unsafe_allow_html=True
394
+ )
 
395
 
396
+ with col2:
 
397
 
398
+ # Prepare data for the radar chart
399
+ rmae_values = accuracy_metrics['rMAE'].tolist()
400
+ categories = accuracy_metrics.index.tolist()
401
+
402
+ fig = go.Figure()
403
+ fig.add_trace(go.Scatterpolar(
404
+ r=rmae_values,
405
+ theta=categories,
406
+ fill='toself',
407
+ name='rMAE'
408
+ ))
409
+
410
+ # Configuring radar chart layout to be smaller
411
+ fig.update_layout(
412
+ width=250, # Adjust width
413
+ height=250, # Adjust height
414
+ margin=dict(t=20, b=20, l=0, r=0), # Remove all margins
415
+ polar=dict(
416
+ radialaxis=dict(
417
+ visible=True,
418
+ range=[0, max(rmae_values) * 1.2] # Adjust range dynamically
419
+ )),
420
+ showlegend=False
421
+ )
422
+
423
+ # Apply CSS class to remove extra space above chart
424
+ st.plotly_chart(fig, use_container_width=True, config={'displayModeBar': False}, className="small-chart")
425
 
426
  st.subheader('ACF plots of Errors')
427
  st.write('The below plots show the ACF (Auto-Correlation Function) for the errors of all three data fields obtained from ENTSO-E: Solar, Wind and Load.')
428
 
429
+ # Dropdown to select the variable
430
+ selected_variable = st.selectbox("Select Variable for ACF of Errors", list(variable_options.keys()))
431
+
432
+ # Get the corresponding columns for the selected variable
433
+ actual_col, forecast_col = variable_options[selected_variable]
434
+
435
+ # Calculate the error and plot ACF if columns are available
436
+ if forecast_col in data.columns:
437
+ obs = data[actual_col]
438
+ pred = data[forecast_col]
439
+ error = pred - obs
440
 
441
+ st.write(f"**ACF of Errors for {selected_variable}**")
442
+ fig, ax = plt.subplots(figsize=(10, 5))
443
+ plot_acf(error.dropna(), ax=ax)
444
+ st.pyplot(fig)
445
 
446
+ # Optionally calculate and store ACF values for further analysis if needed
447
+ acf_values = acf(error.dropna(), nlags=240)
448
 
449
  # Section 3: Insights
450
  elif section == 'Insights':
 
470
  st.pyplot(pairplot_fig)
471
 
472
  elif selected_country == 'Overall':
473
+ st.markdown(
474
+ """
475
+ <style>
476
+ .main-container {
477
+ padding-top: 0px; /* Remove extra padding at the top */
478
+ }
479
+ .chart-spacing {
480
+ margin-top: -40px; /* Adjust this value to control spacing between map and radar plot */
481
+ }
482
+ </style>
483
+ """,
484
+ unsafe_allow_html=True
485
+ )
486
+
487
  st.subheader("Net Load Error Map")
488
  st.write("""
489
  The net load error map highlights the error in the forecasted versus actual net load for each country.
 
497
  filter_df = df[forecast_columns].dropna()
498
  net_load = filter_df['Load_entsoe'] - filter_df['Wind_onshore_entsoe'] - filter_df['Wind_offshore_entsoe'] - filter_df['Solar_entsoe']
499
  net_load_forecast = filter_df['Load_forecast_entsoe'] - filter_df['Wind_onshore_forecast_entsoe'] - filter_df['Wind_offshore_forecast_entsoe'] - filter_df['Solar_forecast_entsoe']
500
+ error = (net_load_forecast - net_load).iloc[-1]
501
  date = filter_df.index[-1].strftime("%Y-%m-%d %H:%M") # Get the latest date in string format
502
  return error, date
503
 
 
571
 
572
  # Call the function to plot the map
573
  plot_net_load_error_map(data_dict)
574
+ # CSS to adjust layout and remove extra spacing
575
 
576
  st.subheader("rMAE of Forecasts published on ENTSO-E TP")
577
  st.write("""