Commit edbbe5c2 authored by lcn's avatar lcn

修复Bug

parent fb18f2f4
from pot_libs.mysql_util.mysql_util import MysqlUtil from pot_libs.mysql_util.mysql_util import MysqlUtil
async def get_kwh_p_dao(table_name, terms, start, end): async def get_kwh_p_dao(terms, start_time, end_time,
sql = f"SELECT create_time,kwh,p FROM {table_name} WHERE cid in %s " \ table_name="company_15min_power",
f"and create_time BETWEEN '{start}' and '{end}'" time_fmt="%%Y-%%m-%%d"):
"""
负荷实际数据
:param terms:
:param start_time:
:param end_time:
:param table_name:
:param time_fmt:
:return:
"""
sql = f"""
select p,kwh,DATE_FORMAT(create_time,"{time_fmt}") as cal_time
from {table_name} where cid in %s and create_time >= %s
and create_time <= %s
"""
async with MysqlUtil() as conn: async with MysqlUtil() as conn:
datas = await conn.fetchall(sql, args=(terms, )) result = await conn.fetchall(sql, args=(terms, start_time, end_time))
return datas return result or []
async def get_pred_p_dao(terms, start, end): async def get_pred_p_dao(terms, start_time, end_time,
sql = f"SELECT create_time,p FROM company_day_ahead_predict " \ time_fmt="%%Y-%%m-%%d"):
f"WHERE cid in %s and create_time BETWEEN '{start}' and '{end}'" """
负荷预测数据
:param terms:
:param start_time:
:param end_time:
:param time_fmt:
:return:
"""
sql = f"""
select avg(p) p ,count(*) p_count,DATE_FORMAT(create_time,
"{time_fmt}") as cal_time
from company_day_ahead_predict
where cid in %s and create_time >= %s and create_time <= %s
group by cal_time
"""
async with MysqlUtil() as conn: async with MysqlUtil() as conn:
datas = await conn.fetchall(sql, args=(terms,)) result = await conn.fetchall(sql, args=(terms, start_time, end_time))
return datas return result or []
\ No newline at end of file
from datetime import datetime from datetime import datetime
import pendulum
from pot_libs.es_util.es_utils import EsUtil from pot_libs.es_util.es_utils import EsUtil
from pot_libs.logger import log from pot_libs.logger import log
from unify_api.constants import COMPANY_15MIN_POWER, COMPANY_DAY_AHEAD_PRE from unify_api.constants import COMPANY_15MIN_POWER, COMPANY_DAY_AHEAD_PRE
...@@ -30,7 +33,7 @@ async def load_forecast_service(cid, cids, start, end): ...@@ -30,7 +33,7 @@ async def load_forecast_service(cid, cids, start, end):
trans_type = "15m" trans_type = "15m"
interval = trans_type interval = trans_type
format = "yyyy-MM-dd HH:mm:ss" format = "yyyy-MM-dd HH:mm:ss"
real_query["aggs"] = { real_query["aggs"] = {
"quarter_time": { "quarter_time": {
"date_histogram": { "date_histogram": {
...@@ -39,7 +42,8 @@ async def load_forecast_service(cid, cids, start, end): ...@@ -39,7 +42,8 @@ async def load_forecast_service(cid, cids, start, end):
"time_zone": "+08:00", "time_zone": "+08:00",
"format": format, "format": format,
}, },
"aggs": {"p": {"stats": {"field": "p"}}, "kwh": {"stats": {"field": "kwh"}}}, "aggs": {"p": {"stats": {"field": "p"}},
"kwh": {"stats": {"field": "kwh"}}},
} }
} }
real_index = COMPANY_15MIN_POWER real_index = COMPANY_15MIN_POWER
...@@ -70,14 +74,16 @@ async def load_forecast_service(cid, cids, start, end): ...@@ -70,14 +74,16 @@ async def load_forecast_service(cid, cids, start, end):
real_value = real_re[slot].get("p").get("sum") real_value = real_re[slot].get("p").get("sum")
real_power_val = ( real_power_val = (
real_re[slot].get("kwh").get("sum") real_re[slot].get("kwh").get("sum")
if type(real_re[slot].get("kwh").get("sum")) in [int, float] if type(real_re[slot].get("kwh").get("sum")) in [int,
float]
else "" else ""
) )
else: else:
real_value = real_re[slot].get("p").get("sum") real_value = real_re[slot].get("p").get("sum")
real_power_val = ( real_power_val = (
real_re[slot].get("kwh").get("sum") real_re[slot].get("kwh").get("sum")
if type(real_re[slot].get("kwh").get("sum")) in [int, float] if type(real_re[slot].get("kwh").get("sum")) in [int,
float]
else "" else ""
) )
real_power_list.append(real_power_val) real_power_list.append(real_power_val)
...@@ -160,8 +166,9 @@ async def load_forecast_service(cid, cids, start, end): ...@@ -160,8 +166,9 @@ async def load_forecast_service(cid, cids, start, end):
pred_power_list=LoadValue(slots=slots, value=pred_power_list), pred_power_list=LoadValue(slots=slots, value=pred_power_list),
deviation_power_list=[], deviation_power_list=[],
) )
count, maxnum, minnum, average, max_index, min_index = choose_list(deviation_list_tmp, 4) count, maxnum, minnum, average, max_index, min_index = choose_list(
deviation_list_tmp, 4)
# 求最大偏差和最小偏差时间 # 求最大偏差和最小偏差时间
max_t = slots[max_index] max_t = slots[max_index]
min_t = slots[min_index] min_t = slots[min_index]
...@@ -183,7 +190,7 @@ async def load_forecast_service(cid, cids, start, end): ...@@ -183,7 +190,7 @@ async def load_forecast_service(cid, cids, start, end):
pred_tmp = [i for i in pred_tmp if i != ""] pred_tmp = [i for i in pred_tmp if i != ""]
total_deviation = abs((sum(pred_tmp) - sum(real_tmp)) / sum(real_tmp)) total_deviation = abs((sum(pred_tmp) - sum(real_tmp)) / sum(real_tmp))
total_deviation = round(total_deviation, 4) total_deviation = round(total_deviation, 4)
deviation_power_list = [] deviation_power_list = []
for index, real_power in enumerate(real_power_list): for index, real_power in enumerate(real_power_list):
if real_power == "" or pred_power_list[index] == "" or real_power == 0: if real_power == "" or pred_power_list[index] == "" or real_power == 0:
...@@ -192,16 +199,17 @@ async def load_forecast_service(cid, cids, start, end): ...@@ -192,16 +199,17 @@ async def load_forecast_service(cid, cids, start, end):
# (预测-实际)/实际 * 100% # (预测-实际)/实际 * 100%
deviation = (pred_power_list[index] - real_power) / real_power deviation = (pred_power_list[index] - real_power) / real_power
deviation_power_list.append(abs(round(deviation, 4))) deviation_power_list.append(abs(round(deviation, 4)))
if ( if (
start.split(" ")[0].rsplit("-", 1)[0] == str(datetime.now().date()).rsplit("-", 1)[0] start.split(" ")[0].rsplit("-", 1)[0] ==
and trans_type == "day" str(datetime.now().date()).rsplit("-", 1)[0]
and trans_type == "day"
): ):
# 如果是本月的,那么当天的电量偏差没有意义, 置为空 # 如果是本月的,那么当天的电量偏差没有意义, 置为空
today_str = str(datetime.now().date()).split("-", 1)[1] today_str = str(datetime.now().date()).split("-", 1)[1]
index = slots.index(today_str) index = slots.index(today_str)
deviation_power_list[index] = "" deviation_power_list[index] = ""
return ForecastResp( return ForecastResp(
pred_data=lv_pred, pred_data=lv_pred,
real_data=lv_real, real_data=lv_real,
...@@ -216,150 +224,139 @@ async def load_forecast_service(cid, cids, start, end): ...@@ -216,150 +224,139 @@ async def load_forecast_service(cid, cids, start, end):
) )
async def load_forecast_service_new15(cid, cids, start, end): async def load_forecast_service_new15(cids, start_time, end_time, interval,
terms = cids if cids else [cid] slots):
time_type = interval_type("range", start, end) if interval == 15 * 60:
if time_type == "day": # 按日
table_name = "company_1day_power" time_fmt = "%%Y-%%m-%%d %%H:%%i"
fmt = "%m-%d" now_time_fmt = "YYYY-MM-DD HH:mm"
to_fmt = "HH:mm"
real_table_name = "company_15min_power"
elif interval == 86400:
# 按月
time_fmt = "%%Y-%%m-%%d"
now_time_fmt = "YYYY-MM-DD"
to_fmt = now_time_fmt
real_table_name = "company_1day_power"
else: else:
table_name = "company_15min_power" # 按年
fmt = "%H:%M" time_fmt = "%%Y-%%m"
datas = await get_kwh_p_dao(table_name, terms, start, end) now_time_fmt = "YYYY-MM"
if not datas: to_fmt = now_time_fmt
return ForecastResp() real_table_name = "company_1day_power"
# 获取slots
intervel, slots = time_pick_transf(start, end) now_time = pendulum.now().format(now_time_fmt)
real_re = sql_time_process(datas, "create_time", fmt) now_month = pendulum.now().format("YYYY-MM")
lv_real = LoadValue()
lv_real.slots = slots # 1,获取实际数据
real_list = [] real_result = await get_kwh_p_dao(cids, start_time, end_time,
real_power_list, pred_power_list = [], [] real_table_name, time_fmt)
# if not real_result:
# return [], [], [], [], [], [], [], 0, "", 0, "", 0, 0
real_data = {i["cal_time"]: i for i in real_result}
real_list, real_power_list = [], []
for slot in slots: for slot in slots:
if slot in real_re: if slot in real_data:
real_value = real_re[slot].get("p") p = real_data[slot]["p"]
real_power_val = ( kwh = real_data[slot]["kwh"]
real_re[slot].get("kwh") if slot > now_time:
if type(real_re[slot].get("kwh")) in [int, float] else "" value, kwh = "", ""
) elif p in [0, 0.0]:
real_power_list.append(real_power_val) value, kwh = 0.0, 0.0
# 值为0是正常数据 elif p:
if real_value in [0, 0.0]: value = round(p, 2)
real_list.append(0.0) kwh = round(kwh, 2)
else: else:
real_list.append(round(real_value, 2) if real_value else "") value, kwh = "", ""
else: else:
real_list.append("") value, kwh = "", ""
real_power_list.append("") real_list.append(value)
lv_real.value = real_list real_power_list.append(kwh)
# 3. 预测数据 # 2,获取预测数据
pred_re = await get_pred_p_dao(terms, start, end) forecast_result = await get_pred_p_dao(cids, start_time, end_time,
if not pred_re: time_fmt)
return ForecastResp() # if not forecast_result:
pred_re = sql_time_process(pred_re, "create_time", fmt) # return [], [], [], [], [], [], [], 0, "", 0, "", 0, 0
lv_pred = LoadValue() forecast_data = {i["cal_time"]: i for i in forecast_result}
lv_pred.slots = slots forecast_list, forecast_power_list = [], []
pred_list = []
for slot in slots: for slot in slots:
if slot in pred_re: if slot in forecast_data:
pred_value = pred_re[slot].get("p") p = forecast_data[slot]["p"]
pred_power_val = ( if p in [0, 0.0]:
round(pred_re[slot].get("p") * 0.25, 2) value = 0.0
if type(pred_re[slot].get("p")) in [int, float] else "" elif p:
) value = round(p, 2)
pred_power_list.append(pred_power_val)
# 值为0是正常数据
if pred_value in [0, 0.0]:
pred_list.append(0.0)
else: else:
pred_list.append(round(pred_value, 2) if pred_value else "") value = ""
else: else:
pred_list.append("") value = ""
pred_power_list.append("") forecast_list.append(value)
lv_pred.value = pred_list if value or value == 0.0:
# 4.求偏差数据 p_count = forecast_data[slot]["p_count"]
deviation_list = [] # 偏差 power_value = round(value * 0.25 * p_count, 2)
deviation_list_abs = [] # 偏差取绝对值, 最大/最小/平均偏差都是绝对值后数据 else:
power_value = ""
forecast_power_list.append(power_value)
# 3.求偏差数据
deviation_list, deviation_power_list = [], [] # 偏差取绝对值, 最大/最小/平均偏差都是绝对值后数据
for num, value in enumerate(real_list): for num, value in enumerate(real_list):
if not value or not pred_list[num]: if not value or not forecast_list[num]:
deviation_list.append("") deviation_list.append("")
else: else:
# (预测-实际)/实际 * 100% # (预测-实际)/实际 * 100%
deviation = (pred_list[num] - value) / value deviation = (forecast_list[num] - value) / value
deviation_list.append(round(deviation, 4)) deviation_list.append(abs(round(deviation, 4)))
deviation_list_abs.append(abs(round(deviation, 4)))
# 取绝对值,并保留 for num, value in enumerate(real_power_list):
deviation_list_tmp = [i for i in deviation_list_abs if i != ""] if not value or not forecast_power_list[num]:
log.info(f"deviation_list_tmp:{deviation_list_tmp}, " deviation_power = ""
f"deviation_list_abs:{deviation_list_abs}")
if not deviation_list_tmp:
return ForecastResp(
pred_data=lv_pred,
real_data=lv_real,
deviation_list=deviation_list_abs,
max_deviation=[],
min_deviation=[],
avg_deviation="",
total_deviation="",
real_power_list=LoadValue(slots=slots, value=real_power_list),
pred_power_list=LoadValue(slots=slots, value=pred_power_list),
deviation_power_list=[],
)
count, maxnum, minnum, average, max_index, min_index = choose_list(
deviation_list_tmp, 4)
# 求最大偏差和最小偏差时间
max_t = slots[max_index]
min_t = slots[min_index]
if time_type == "day":
max_time = start[:4] + "-" + max_t
min_time = start[:4] + "-" + min_t
else:
max_time = start.split(" ")[0] + " " + max_t
min_time = start.split(" ")[0] + " " + min_t
# 最大偏差
max_deviation = [maxnum, max_time]
# 最小偏差
min_deviation = [minnum, min_time]
# 平均偏差
avg_deviation = average
# 总量偏差 = | (预测(总) - 实际(总)) / 实际(总) | * 100%
real_tmp = [i for i in real_list if i != ""]
pred_tmp = pred_list[: len(real_tmp)]
pred_tmp = [i for i in pred_tmp if i != ""]
total_deviation = abs((sum(pred_tmp) - sum(real_tmp)) / sum(real_tmp))
total_deviation = round(total_deviation, 4)
deviation_power_list = []
for index, real_power in enumerate(real_power_list):
if real_power == "" or pred_power_list[index] == "" or real_power == 0:
deviation_power_list.append("")
else: else:
# (预测-实际)/实际 * 100% # (预测-实际)/实际 * 100%
deviation = (pred_power_list[index] - real_power) / real_power deviation_power = (forecast_power_list[num] - value) / value
deviation_power_list.append(abs(round(deviation, 4))) deviation_power = abs(round(deviation_power, 4))
if (
start.split(" ")[0].rsplit("-", 1)[0] ==
str(datetime.now().date()).rsplit("-", 1)[0]
and time_type == "day"
):
# 如果是本月的,那么当天的电量偏差没有意义, 置为空 # 如果是本月的,那么当天的电量偏差没有意义, 置为空
today_str = str(datetime.now().date()).split("-", 1)[1] if interval == 86400 and now_month == start_time[:7] and \
index = slots.index(today_str) num == slots.index(now_time):
deviation_power_list[index] = "" deviation_power = ""
deviation_power_list.append(deviation_power)
# 4,求偏差统计值
deviation_list_tmp = [i for i in deviation_list if i != ""]
if deviation_list_tmp:
count, max_deviation, min_deviation, average, max_index, min_index = \
choose_list(deviation_list_tmp, 4)
# 求最大偏差和最小偏差时间
max_time = slots[max_index]
min_time = slots[min_index]
# 平均偏差
avg_deviation = average
# 总量偏差 = | (预测(总) - 实际(总)) / 实际(总) | * 100%
real_tmp = [i for i in real_list if i != ""]
pred_tmp = forecast_list[: len(real_tmp)]
pred_tmp = [i for i in pred_tmp if i != ""]
total_deviation = abs((sum(pred_tmp) - sum(real_tmp)) / sum(real_tmp))
total_deviation = round(total_deviation, 4)
else:
max_deviation, max_time, min_deviation, min_time = 0, "", 0, ""
avg_deviation, total_deviation = 0, 0
# 重置 slots
if interval == 15 * 60:
for num, slot in enumerate(slots):
slot = pendulum.parse(slot).format("HH:mm")
slots[num] = slot
return ForecastResp( return ForecastResp(
pred_data=lv_pred, pred_data=LoadValue(slots=slots, value=real_list),
real_data=lv_real, real_data=LoadValue(slots=slots, value=forecast_list),
deviation_list=deviation_list_abs, deviation_list=deviation_list,
max_deviation=max_deviation, max_deviation=max_deviation,
min_deviation=min_deviation, min_deviation=min_deviation,
avg_deviation=avg_deviation, avg_deviation=avg_deviation,
total_deviation=total_deviation, total_deviation=total_deviation,
real_power_list=LoadValue(slots=slots, value=real_power_list), real_power_list=LoadValue(slots=slots, value=real_power_list),
pred_power_list=LoadValue(slots=slots, value=pred_power_list), pred_power_list=LoadValue(slots=slots, value=forecast_power_list),
deviation_power_list=deviation_power_list, deviation_power_list=deviation_power_list,
) )
...@@ -5,6 +5,7 @@ from unify_api.modules.load_analysis.components.load_forecast_cps import ( ...@@ -5,6 +5,7 @@ from unify_api.modules.load_analysis.components.load_forecast_cps import (
) )
from unify_api.modules.load_analysis.service.load_forecast_service import \ from unify_api.modules.load_analysis.service.load_forecast_service import \
load_forecast_service, load_forecast_service_new15 load_forecast_service, load_forecast_service_new15
from unify_api.utils.time_format import time_pick_transf_new
@summary("负荷预测") @summary("负荷预测")
...@@ -17,4 +18,8 @@ async def post_load_forecast(req, body: ForecastReq) -> ForecastResp: ...@@ -17,4 +18,8 @@ async def post_load_forecast(req, body: ForecastReq) -> ForecastResp:
# 管理版本多个工厂的情况, 兼容能力最强的参数cids, 保留旧有的cid: # 管理版本多个工厂的情况, 兼容能力最强的参数cids, 保留旧有的cid:
cids = body.cids cids = body.cids
# return await load_forecast_service(cid, cids, start, end) # return await load_forecast_service(cid, cids, start, end)
return await load_forecast_service_new15(cid, cids, start, end) terms = cids if cids else [cid]
# 获取时间差
interval, slots = time_pick_transf_new(start, end)
return await load_forecast_service_new15(terms, start, end,
interval, slots)
...@@ -60,6 +60,41 @@ def time_pick_transf(start, end, is_range=0): ...@@ -60,6 +60,41 @@ def time_pick_transf(start, end, is_range=0):
return intervel, slots return intervel, slots
def time_pick_transf_new(start, end):
"""获取intervel和slots, 详细显示时间轴信息,新接口都使用这个来获取时间"""
start_f = my_pendulum.from_format(start, 'YYYY-MM-DD HH:mm:ss')
end_f = my_pendulum.from_format(end, 'YYYY-MM-DD HH:mm:ss')
diff = end_f.int_timestamp - start_f.int_timestamp
# 1. 计算intervel
# 1.1 区间48小时之内, 返回15min
if diff <= 48 * 3600:
intervel = 15 * 60
# 1.2 区间在60天以内, 返回1day
elif 48 * 3600 < diff <= 60 * 86400:
intervel = 86400
# 1.3 选择年, 返回1个月
else:
intervel = 30 * 86400
# 2. 计算slots
# 2.1 取到点的个数, 比如15min的96个点
slots = []
slot_num = round((end_f.int_timestamp - start_f.int_timestamp) / intervel)
for i in range(slot_num):
# 区间48小时之内
if diff <= 48 * 3600:
dt = start_f.add(minutes=15 * i).format("YYYY-MM-DD HH:mm")
dt_str = str(dt)
# 区间在60天以内
elif 48 * 3600 < diff <= 60 * 86400:
dt = start_f.add(days=1 * i).format("YYYY-MM-DD")
dt_str = str(dt)
else:
dt = start_f.add(months=1 * i).format("YYYY-MM")
dt_str = str(dt)
slots.append(dt_str)
return intervel, slots
def power_slots(start, end): def power_slots(start, end):
"""电量电费,用电统计,time=range slots计算""" """电量电费,用电统计,time=range slots计算"""
start_f = my_pendulum.from_format(start, 'YYYY-MM-DD HH:mm:ss') start_f = my_pendulum.from_format(start, 'YYYY-MM-DD HH:mm:ss')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment