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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -47
app.py CHANGED
@@ -15,6 +15,7 @@ from datetime import datetime
15
  import folium
16
  import seaborn as sns
17
  from streamlit_folium import st_folium
 
18
 
19
 
20
  def get_current_time():
@@ -156,15 +157,6 @@ if selected_country != 'Overall':
156
  st.sidebar.subheader("Section")
157
  st.sidebar.caption("Select the type of information you want to explore.")
158
  section = st.sidebar.radio('', ['Data Quality', 'Forecasts Quality', 'Insights'], index=1)
159
- date_range = st.sidebar.date_input("Select Date Range for Metrics Calculation:",
160
- value=(pd.to_datetime("2024-01-01"), pd.to_datetime(pd.Timestamp('today'))))
161
- if len(date_range) == 2:
162
- start_date = pd.Timestamp(date_range[0])
163
- end_date = pd.Timestamp(date_range[1])
164
- else:
165
- st.error("Please select a valid date range.")
166
- st.stop()
167
-
168
  else:
169
  section = None # No section is shown when "Overall" is selected
170
 
@@ -218,8 +210,12 @@ if section == 'Data Quality':
218
 
219
  st.header('Data Quality')
220
 
221
- st.write('The table below presents the data quality metrics for various energy-related datasets, focusing on the percentage of missing values and the occurrence of extreme or nonsensical values for the selected country.')
222
- data_quality=data.iloc[:-28]
 
 
 
 
223
 
224
  # Report % of missing values
225
  missing_values = data_quality[forecast_columns].isna().mean() * 100
@@ -315,7 +311,7 @@ elif section == 'Forecasts Quality':
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
@@ -329,7 +325,7 @@ elif section == 'Forecasts Quality':
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)
@@ -338,7 +334,21 @@ elif section == 'Forecasts Quality':
338
 
339
  st.subheader('Accuracy Metrics (Sorted by rMAE):')
340
 
341
- output_text = f"The below metrics are calculated from the selected date range from {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}. This interval can be adjusted from the sidebar."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  st.write(output_text)
343
 
344
  data = data.loc[start_date:end_date]
@@ -424,7 +434,7 @@ elif section == 'Forecasts Quality':
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()))
@@ -449,20 +459,28 @@ elif section == 'Forecasts Quality':
449
  # Section 3: Insights
450
  elif section == 'Insights':
451
  st.header("Insights")
452
- st.write("""
453
- This section provides insights derived from the data and forecasts.
454
- You can visualize trends, anomalies, and other important findings.
455
- """)
456
 
457
- # Scatter plots for correlation between wind, solar, and load
458
- st.subheader('Correlation between Wind, Solar, Load and Weather Features')
459
- st.write('The below scatter plots are made for checking whether there exists a correlation between the data fields obtained: Solar, Wind, Load and Weather Features.')
460
 
461
- selected_columns=['Load_entsoe', 'Solar_entsoe', 'Wind_offshore_entsoe', 'Wind_onshore_entsoe'] + weather_columns
462
- selected_df=data[selected_columns]
 
 
 
 
 
 
 
 
 
463
  selected_df.columns = [col.replace('_entsoe', '').replace('_', ' ') for col in selected_df.columns]
 
 
464
  selected_df = selected_df.dropna()
465
- print(selected_df)
 
466
  sns.set_theme(style="ticks")
467
  pairplot_fig = sns.pairplot(selected_df)
468
 
@@ -470,19 +488,6 @@ 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("""
@@ -544,7 +549,7 @@ elif selected_country == 'Overall':
544
  fill_opacity=0.7,
545
  line_opacity=0.5,
546
  line_color="black", # Neutral border color
547
- legend_name="Net Load Error"
548
  ).add_to(m)
549
 
550
  # Add a GeoJson layer with custom tooltip for country, error, and date
@@ -553,7 +558,7 @@ elif selected_country == 'Overall':
553
  style_function=lambda x: {'fillOpacity': 0, 'color': 'black', 'weight': 0},
554
  tooltip=folium.GeoJsonTooltip(
555
  fields=["name", "net_load_error", "date"],
556
- aliases=["Country:", "Net Load Error:", "Date:"],
557
  localize=True
558
  )
559
  ).add_to(m)
@@ -568,15 +573,10 @@ elif selected_country == 'Overall':
568
  'Germany': Data_DE,
569
  'Netherlands': Data_NL
570
  }
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("""
578
- The radar chart below compares the forecast accuracy across Load, Onshore Wind, Offshore Wind, and Solar for each country.
579
- """)
580
 
581
  def calculate_mae(actual, forecast):
582
  return np.mean(np.abs(actual - forecast))
@@ -611,10 +611,11 @@ elif selected_country == 'Overall':
611
  angles = ['Load', 'Wind_onshore', 'Wind_offshore', 'Solar']
612
  for _, row in rmae_df.iterrows():
613
  fig.add_trace(go.Scatterpolar(r=[row[angle] for angle in angles], theta=angles, fill='toself', name=row['Country']))
614
- fig.update_layout(polar=dict(radialaxis=dict(visible=True, range=[0, 2])), showlegend=True, title="rMAE Radar Chart by Country")
615
  st.plotly_chart(fig)
616
 
617
  # Main execution to create and display radar plot
618
  rmae_df = create_rmae_dataframe(data_dict)
619
  plot_rmae_radar_chart(rmae_df)
 
620
 
 
15
  import folium
16
  import seaborn as sns
17
  from streamlit_folium import st_folium
18
+ import datetime
19
 
20
 
21
  def get_current_time():
 
157
  st.sidebar.subheader("Section")
158
  st.sidebar.caption("Select the type of information you want to explore.")
159
  section = st.sidebar.radio('', ['Data Quality', 'Forecasts Quality', 'Insights'], index=1)
 
 
 
 
 
 
 
 
 
160
  else:
161
  section = None # No section is shown when "Overall" is selected
162
 
 
210
 
211
  st.header('Data Quality')
212
 
213
+ st.write('The table below presents the data quality metrics focusing on the percentage of missing values and the occurrence of extreme or nonsensical values for the selected country.')
214
+
215
+ yesterday_midnight = pd.Timestamp(datetime.datetime.now().date() - pd.Timedelta(days=1)).replace(hour=23, minute=59, second=59)
216
+
217
+ # Filter data until the end of yesterday (midnight)
218
+ data_quality = data[data.index <= yesterday_midnight]
219
 
220
  # Report % of missing values
221
  missing_values = data_quality[forecast_columns].isna().mean() * 100
 
311
 
312
  # Scatter plots for error distribution
313
  st.subheader('Error Distribution')
314
+ st.write('The below scatter plots show the error distribution of all four fields: Solar, Wind Onshore, Wind Offshore and Load.')
315
  selected_variable = st.selectbox("Select Variable for Error Distribution", list(variable_options.keys()))
316
 
317
  # Get the corresponding columns for the selected variable
 
325
 
326
  # Calculate error and plot
327
  error = pred - obs
328
+ fig = px.scatter(x=obs, y=pred, labels={'x': 'Observed [MW]', 'y': 'Forecast ENTSO-E [MW]'})
329
  fig.update_layout(title=f'Error Distribution for {selected_variable}')
330
 
331
  st.plotly_chart(fig)
 
334
 
335
  st.subheader('Accuracy Metrics (Sorted by rMAE):')
336
 
337
+
338
+ date_range = st.date_input(
339
+ "Select Date Range for Metrics Calculation:",
340
+ value=(pd.to_datetime("2024-01-01"), pd.to_datetime(pd.Timestamp('today')))
341
+ )
342
+
343
+ if len(date_range) == 2:
344
+ start_date = pd.Timestamp(date_range[0])
345
+ end_date = pd.Timestamp(date_range[1])
346
+ else:
347
+ st.error("Please select a valid date range.")
348
+ st.stop()
349
+
350
+
351
+ output_text = f"The below metrics are calculated from the selected date range from {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}. "
352
  st.write(output_text)
353
 
354
  data = data.loc[start_date:end_date]
 
434
  st.plotly_chart(fig, use_container_width=True, config={'displayModeBar': False}, className="small-chart")
435
 
436
  st.subheader('ACF plots of Errors')
437
+ 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 Onshore, Wind Offshore and Load.')
438
 
439
  # Dropdown to select the variable
440
  selected_variable = st.selectbox("Select Variable for ACF of Errors", list(variable_options.keys()))
 
459
  # Section 3: Insights
460
  elif section == 'Insights':
461
  st.header("Insights")
 
 
 
 
462
 
463
+ st.write('The scatter plots below are created to explore possible correlations between the data fields: Solar, Wind Onshore, Wind Offshore, Load, and Weather Features.')
464
+ # Add a selection box for the data resolution (weekly, daily, hourly)
465
+ data_2024 = data[data.index.year == 2024]
466
 
467
+ resolution = st.selectbox('Select data resolution:', ['Daily', 'Hourly'])
468
+
469
+ # Resample data based on the selected resolution
470
+ if resolution == 'Hourly':
471
+ resampled_data = data_2024
472
+ elif resolution == 'Daily':
473
+ resampled_data = data_2024.resample('D').mean() # Resample to daily mean
474
+
475
+ # Select the necessary columns for the scatter plot
476
+ selected_columns = ['Load_entsoe', 'Solar_entsoe', 'Wind_offshore_entsoe', 'Wind_onshore_entsoe'] + weather_columns
477
+ selected_df = resampled_data[selected_columns]
478
  selected_df.columns = [col.replace('_entsoe', '').replace('_', ' ') for col in selected_df.columns]
479
+
480
+ # Drop missing values
481
  selected_df = selected_df.dropna()
482
+
483
+ # Create the scatter plots using seaborn's pairplot
484
  sns.set_theme(style="ticks")
485
  pairplot_fig = sns.pairplot(selected_df)
486
 
 
488
  st.pyplot(pairplot_fig)
489
 
490
  elif selected_country == 'Overall':
 
 
 
 
 
 
 
 
 
 
 
 
 
491
 
492
  st.subheader("Net Load Error Map")
493
  st.write("""
 
549
  fill_opacity=0.7,
550
  line_opacity=0.5,
551
  line_color="black", # Neutral border color
552
+ legend_name="Net Load Error [MW]"
553
  ).add_to(m)
554
 
555
  # Add a GeoJson layer with custom tooltip for country, error, and date
 
558
  style_function=lambda x: {'fillOpacity': 0, 'color': 'black', 'weight': 0},
559
  tooltip=folium.GeoJsonTooltip(
560
  fields=["name", "net_load_error", "date"],
561
+ aliases=["Country:", "Net Load Error [MW]:", "Date:"],
562
  localize=True
563
  )
564
  ).add_to(m)
 
573
  'Germany': Data_DE,
574
  'Netherlands': Data_NL
575
  }
 
 
576
  plot_net_load_error_map(data_dict)
 
577
 
578
  st.subheader("rMAE of Forecasts published on ENTSO-E TP")
579
+ st.write("""The rMAE of Forecasts chart compares the forecast accuracy of the predictions published by ENTSO-E Transparency Platform for Belgium, Germany, France, and the Netherlands. It shows the rMAE for onshore wind, offshore wind, solar, and load demand, highlighting how well forecasts perform relative to a basic persistence model across these countries and energy sectors.""")
 
 
580
 
581
  def calculate_mae(actual, forecast):
582
  return np.mean(np.abs(actual - forecast))
 
611
  angles = ['Load', 'Wind_onshore', 'Wind_offshore', 'Solar']
612
  for _, row in rmae_df.iterrows():
613
  fig.add_trace(go.Scatterpolar(r=[row[angle] for angle in angles], theta=angles, fill='toself', name=row['Country']))
614
+ fig.update_layout(polar=dict(radialaxis=dict(visible=True, range=[0, 1.2])), showlegend=True, title="rMAE Radar Chart by Country")
615
  st.plotly_chart(fig)
616
 
617
  # Main execution to create and display radar plot
618
  rmae_df = create_rmae_dataframe(data_dict)
619
  plot_rmae_radar_chart(rmae_df)
620
+
621