|
@@ -1,5 +1,5 @@
|
|
# -*- coding: utf-8 -*-
|
|
# -*- coding: utf-8 -*-
|
|
-from plotly.subplots import make_subplots
|
|
|
|
|
|
+import numpy as np
|
|
from flask import Flask,request
|
|
from flask import Flask,request
|
|
import time
|
|
import time
|
|
import random
|
|
import random
|
|
@@ -11,10 +11,11 @@ import plotly.express as px
|
|
import plotly.graph_objects as go
|
|
import plotly.graph_objects as go
|
|
import pandas as pd
|
|
import pandas as pd
|
|
import plotly.io as pio
|
|
import plotly.io as pio
|
|
-
|
|
|
|
|
|
+from bson.decimal128 import Decimal128
|
|
|
|
+import numbers
|
|
app = Flask('analysis_report——service')
|
|
app = Flask('analysis_report——service')
|
|
|
|
|
|
-def put_analysis_report_to_html(args,df_clean,df_accuracy):
|
|
|
|
|
|
+def put_analysis_report_to_html(args,df_clean, df_predict, df_accuracy):
|
|
col_time = args['col_time']
|
|
col_time = args['col_time']
|
|
col_x_env = args['col_x_env']
|
|
col_x_env = args['col_x_env']
|
|
col_x_pre = args['col_x_pre']
|
|
col_x_pre = args['col_x_pre']
|
|
@@ -139,29 +140,109 @@ def put_analysis_report_to_html(args,df_clean,df_accuracy):
|
|
# -------------------- 预测功率与实际功率曲线 --------------------
|
|
# -------------------- 预测功率与实际功率曲线 --------------------
|
|
|
|
|
|
# 生成折线图(以 C_GLOBALR 和 NWP预测总辐射 为例)
|
|
# 生成折线图(以 C_GLOBALR 和 NWP预测总辐射 为例)
|
|
- fig_line = px.line(df_clean, x='dateTime', y=[label, label_pre], markers=True)
|
|
|
|
|
|
+ # 创建一个图表对象
|
|
|
|
+ fig = go.Figure()
|
|
|
|
|
|
- # 自定义趋势图布局
|
|
|
|
- fig_line.update_layout(
|
|
|
|
- template='seaborn',
|
|
|
|
- # title=dict(text=f"{label_pre}与{label}曲线",
|
|
|
|
- # x=0.5, font=dict(size=24, color='darkblue')),
|
|
|
|
- plot_bgcolor='rgba(255, 255, 255, 0.8)', # 改为白色背景
|
|
|
|
|
|
+ # 获取所有的模型
|
|
|
|
+ models = df_predict['model'].unique()
|
|
|
|
+ # 添加实际功率曲线
|
|
|
|
+ fig.add_trace(go.Scatter(
|
|
|
|
+ x=df_predict[col_time],
|
|
|
|
+ y=df_predict[label],
|
|
|
|
+ mode='lines+markers',
|
|
|
|
+ name='实际功率', # 实际功率
|
|
|
|
+ line=dict(dash='dot', width=2), # 虚线
|
|
|
|
+ marker=dict(symbol='cross'),
|
|
|
|
+ ))
|
|
|
|
+ # 为每个模型添加预测值和实际功率的曲线
|
|
|
|
+ for model in models:
|
|
|
|
+ # 筛选该模型的数据
|
|
|
|
+ model_data = df_predict[df_predict['model'] == model]
|
|
|
|
+
|
|
|
|
+ # 添加预测值曲线
|
|
|
|
+ fig.add_trace(go.Scatter(
|
|
|
|
+ x=model_data[col_time],
|
|
|
|
+ y=model_data[label_pre],
|
|
|
|
+ mode='lines+markers',
|
|
|
|
+ name=f'{model} 预测值', # 预测值
|
|
|
|
+ marker=dict(symbol='circle'),
|
|
|
|
+ line=dict(width=2)
|
|
|
|
+ ))
|
|
|
|
+
|
|
|
|
+ # 设置图表的标题和标签
|
|
|
|
+ fig.update_layout(
|
|
|
|
+ template='seaborn', # 使用 seaborn 模板
|
|
|
|
+ title=dict(
|
|
|
|
+ text=f"{label_pre} 与 {label} 对比", # 标题
|
|
|
|
+ x=0.5, font=dict(size=20, color='darkblue') # 标题居中并设置字体大小和颜色
|
|
|
|
+ ),
|
|
|
|
+ plot_bgcolor='rgba(255, 255, 255, 0.8)', # 背景色
|
|
xaxis=dict(
|
|
xaxis=dict(
|
|
showgrid=True,
|
|
showgrid=True,
|
|
gridcolor='rgba(200, 200, 200, 0.5)', # 网格线颜色
|
|
gridcolor='rgba(200, 200, 200, 0.5)', # 网格线颜色
|
|
|
|
+ title='时间', # 时间轴标题
|
|
rangeslider=dict(visible=True), # 显示滚动条
|
|
rangeslider=dict(visible=True), # 显示滚动条
|
|
rangeselector=dict(visible=True) # 显示预设的时间范围选择器
|
|
rangeselector=dict(visible=True) # 显示预设的时间范围选择器
|
|
),
|
|
),
|
|
- yaxis=dict(showgrid=True, gridcolor='rgba(200, 200, 200, 0.5)'),
|
|
|
|
- legend=dict(x=0.01, y=0.99, bgcolor='rgba(255, 255, 255, 0.7)', bordercolor='black', borderwidth=1)
|
|
|
|
|
|
+ yaxis=dict(
|
|
|
|
+ showgrid=True,
|
|
|
|
+ gridcolor='rgba(200, 200, 200, 0.5)',
|
|
|
|
+ title='功率' # y轴标题
|
|
|
|
+ ),
|
|
|
|
+ legend=dict(
|
|
|
|
+ x=0.01,
|
|
|
|
+ y=0.99,
|
|
|
|
+ bgcolor='rgba(255, 255, 255, 0.7)', # 背景透明
|
|
|
|
+ bordercolor='black',
|
|
|
|
+ borderwidth=1,
|
|
|
|
+ font=dict(size=12) # 字体大小
|
|
|
|
+ ),
|
|
|
|
+ hovermode='x unified', # 鼠标悬停时显示统一的提示框
|
|
|
|
+ hoverlabel=dict(
|
|
|
|
+ bgcolor='white',
|
|
|
|
+ font_size=14,
|
|
|
|
+ font_family="Rockwell", # 设置字体样式
|
|
|
|
+ bordercolor='black'
|
|
|
|
+ ),
|
|
|
|
+ margin=dict(l=50, r=50, t=50, b=50) # 调整边距,避免标题或标签被遮挡
|
|
)
|
|
)
|
|
-
|
|
|
|
# 将折线图保存为 HTML 片段
|
|
# 将折线图保存为 HTML 片段
|
|
- power_html = pio.to_html(fig_line, full_html=False)
|
|
|
|
|
|
+ power_html = pio.to_html(fig, full_html=False)
|
|
|
|
|
|
# -------------------- 准确率表展示--------------------
|
|
# -------------------- 准确率表展示--------------------
|
|
acc_html = df_accuracy.to_html(classes='table table-bordered table-striped', index=False)
|
|
acc_html = df_accuracy.to_html(classes='table table-bordered table-striped', index=False)
|
|
|
|
+ # -------------------- 准确率汇总展示--------------------
|
|
|
|
+ # 指定需要转换的列
|
|
|
|
+ cols_to_convert = ['MAE', 'accuracy', 'RMSE', 'deviationElectricity','deviationAssessment']
|
|
|
|
+ for col in cols_to_convert :
|
|
|
|
+ if col in df_accuracy.columns:
|
|
|
|
+ df_accuracy[col] = df_accuracy[col].apply(
|
|
|
|
+ lambda x: float(x.to_decimal()) if isinstance(x, Decimal128) else float(x) if isinstance(x, numbers.Number) else np.nan)
|
|
|
|
+
|
|
|
|
+ # 确定存在的列
|
|
|
|
+ agg_dict = {}
|
|
|
|
+ rename_cols = ['model']
|
|
|
|
+ if 'MAE' in df_accuracy.columns:
|
|
|
|
+ agg_dict['MAE'] = np.nanmean
|
|
|
|
+ rename_cols.append('MAE平均值')
|
|
|
|
+ if 'accuracy' in df_accuracy.columns:
|
|
|
|
+ agg_dict['accuracy'] = np.nanmean
|
|
|
|
+ rename_cols.append('准确率平均值')
|
|
|
|
+ if 'RMSE' in df_accuracy.columns:
|
|
|
|
+ agg_dict['RMSE'] = np.nanmean
|
|
|
|
+ rename_cols.append('RMSE平均值')
|
|
|
|
+ if 'deviationElectricity' in df_accuracy.columns:
|
|
|
|
+ agg_dict['deviationElectricity'] = [np.nanmean, np.nansum]
|
|
|
|
+ rename_cols.append('考核电量平均值')
|
|
|
|
+ rename_cols.append('考核总电量')
|
|
|
|
+ if 'deviationAssessment' in df_accuracy.columns:
|
|
|
|
+ agg_dict['deviationAssessment'] = [np.nanmean, np.nansum]
|
|
|
|
+ rename_cols.append('考核分数平均值')
|
|
|
|
+ rename_cols.append('考核总分数')
|
|
|
|
+ # 进行分组聚合,如果有需要聚合的列
|
|
|
|
+ summary_df = df_accuracy.groupby('model').agg(agg_dict).reset_index()
|
|
|
|
+ summary_df.columns =rename_cols
|
|
|
|
+ summary_html = summary_df.to_html(classes='table table-bordered table-striped', index=False)
|
|
# -------------------- 生成完整 HTML 页面 --------------------
|
|
# -------------------- 生成完整 HTML 页面 --------------------
|
|
|
|
|
|
html_content = f"""
|
|
html_content = f"""
|
|
@@ -201,6 +282,8 @@ def put_analysis_report_to_html(args,df_clean,df_accuracy):
|
|
overflow-x: auto; /* 水平滚动条 */
|
|
overflow-x: auto; /* 水平滚动条 */
|
|
max-width: 100%; /* 限制宽度 */
|
|
max-width: 100%; /* 限制宽度 */
|
|
white-space: nowrap; /* 防止内容换行 */
|
|
white-space: nowrap; /* 防止内容换行 */
|
|
|
|
+ max-height: 500px; /* 限制高度 */
|
|
|
|
+ overflow-y: auto; /* 显示垂直滚动条 */
|
|
}}
|
|
}}
|
|
table {{
|
|
table {{
|
|
width: 100%;
|
|
width: 100%;
|
|
@@ -249,6 +332,11 @@ def put_analysis_report_to_html(args,df_clean,df_accuracy):
|
|
<h2>8. 准确率对比</h2>
|
|
<h2>8. 准确率对比</h2>
|
|
{acc_html}
|
|
{acc_html}
|
|
</div>
|
|
</div>
|
|
|
|
+ <!-- Pandas DataFrame 表格 -->
|
|
|
|
+ <div class="table-container">
|
|
|
|
+ <h2>9. 准确率汇总对比</h2>
|
|
|
|
+ {summary_html}
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</body>
|
|
</html>
|
|
</html>
|
|
@@ -277,8 +365,8 @@ def analysis_report():
|
|
print('args',args)
|
|
print('args',args)
|
|
logger.info(args)
|
|
logger.info(args)
|
|
#获取数据
|
|
#获取数据
|
|
- df_clean, df_accuracy = get_df_list_from_mongo(args)[0], get_df_list_from_mongo(args)[1]
|
|
|
|
- path = put_analysis_report_to_html(args, df_clean, df_accuracy)
|
|
|
|
|
|
+ df_clean, df_predict, df_accuracy = get_df_list_from_mongo(args)[0], get_df_list_from_mongo(args)[1],get_df_list_from_mongo(args)[2]
|
|
|
|
+ path = put_analysis_report_to_html(args, df_clean, df_predict, df_accuracy)
|
|
success = 1
|
|
success = 1
|
|
except Exception as e:
|
|
except Exception as e:
|
|
my_exception = traceback.format_exc()
|
|
my_exception = traceback.format_exc()
|