全国居民用电数据可视化——负荷预测
1. 电力系统的负荷预测
提高电力系统负荷预测的准确度,可以提高电网运行的安全性和经济性,并可以改善供电质量。
1)负荷预测的步骤:分析历史数据,找出负荷变化规律,建立预测模型。
2)预测模型:主要分为两种模型,第一种模型为线性变化型模型,第二种模型为周期型模型。
(1)线性变化型模型
(2)周期型模型
注:如果按照线性变化型模型预测出次日平均负荷,按周期型模型预测出次日负荷周期变化系数,将其相乘便可得到次日负荷预测值。
3)日负荷预测算法——最小二乘法
注:线性回归也可使用!!!
4)模型适用范围:对于年或者周负荷预测适用于线性增加型和周期型合成的日负荷变化模型。
2. 全国居民用电数据在2021年的预测
该功能为预测全国各个省份、自治区以及直辖市在2021年的居民用电数据。其中红线为预测值(即y = ax + b),绿色的点为实际值。
重要代码:1)controller类中的方法:用于预测2021年的数据,并且将处理好的数据返回给http客户端来做处理,可视化(主要使用到Apache Echarts)处理在这里不做介绍。
/**
* 预测在2021年的数据
*
* @return 返回预测后的数据
*/
@RequestMapping("/pred")
public Object pred(@RequestParam(value = "name", defaultValue = "江苏") String name,
@RequestParam(value = "year", defaultValue = "2021") int year) {
Map<String, Object> result = new HashMap<>();
// 查询需要显示地名,如果需要查询的地名不在map映射中,则提示报错
if (!map.containsKey(name)) {
result.put("status", 400);
result.put("message", "查询条件 name 错误");
return result;
}
// 查询需要显示的年份,如果需要查询的年份小于2020年,则提示报错
if (year < 2020) {
result.put("status", 400);
result.put("message", "查询条件 year 错误");
return result;
}
// 从数据库中获取得到全国各个省份、自治区以及直辖市的居民用电量
List<DataModel> dataModels = chinaProvinceDataRepository.findAll()
// 将从数据库中获取得到的数据转换成数据流
.stream()
// 根据地名来将数据进行筛选
.filter(e -> e.getCpd_name().equals(map.get(name)))
// 获取得到具体的省份、自治区以及直辖市的居民用电量,并且按照年份以及数据的形式来存储
.map(e -> {
Map<String, Integer> map = new HashMap<>();
map.put("year", Integer.parseInt(e.getCpd_date().substring(0, 4)));
map.put("data", (int) e.getCpd_data());
return map;
})
// 同时根据年份来对数据进行排序
.sorted(Comparator.comparingInt(e -> e.get("year")))
// 最后将数据存储在集合中
.map(e -> {
System.out.println("year" + e.get("year"));
System.out.println("data" + e.get("data"));
return new DataModel(e.get("year") - 2000, e.get("data"));
})
.collect(Collectors.toList());
System.out.println(dataModels);
// 最小二乘法
LinerRegressionModel regressionModel = new LinerRegressionModel(dataModels);
// 计算 a 和 b
// 其中abs[0] = a,abs[1] = b
double[] abs = regressionModel.least_square_method();
System.out.println(Arrays.toString(abs));
// 获得预测的值
double pred = abs[0] * (year - 2000) + abs[1];
result.put("status", 200);
result.put("message", "预测成功");
dataModels = dataModels.stream()
// 将原来的2000相加,显示初始的年份
.peek(e -> e.setX(e.getX() + 2000))
.collect(Collectors.toList());
// 将预测的数据放入dataModels中
dataModels.add(new DataModel(year, (int) pred));
result.put("data", dataModels);
return result;
}
2)Datamodel实体类(代码块1)中调用),用于存放一次直线(即y = ax + b)中的x和y,其中x为年份,y为用电量;
public class DataModel {
private int x;
private int y;
public DataModel(int x, int y) {
this.x = x;
this.y = y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public String toString() {
return "{x=" + x + ", y=" + y + "}";
}
}
3)LinerRegressionModel类(代码块1)中调用)——最小二乘法的核心代码
import java.util.List;
public class LinerRegressionModel {
// 定义一个数据表格
private List<DataModel> dataModel;
public LinerRegressionModel(List<DataModel> dataModel) {
this.dataModel = dataModel;
}
public void log(double a, double b) {
System.out.println("计算出的线性函数为: y = " + a + "x" + b);
}
/**
*
* 利用最小二乘法计算 a 和 b
*
* @return
*/
public double[] least_square_method() {
double sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0;
for (DataModel dataModel1 : dataModel) {
sum_x += dataModel1.getX();
sum_y += dataModel1.getY();
sum_xy += dataModel1.getX() * dataModel1.getY();
sum_xx += dataModel1.getX() ^ 2;
}
double a = (sum_xy - (1.0 / dataModel.size()) * sum_x * sum_y) / (sum_xx - (1.0 / dataModel.size()) * (((int) sum_x) ^ 2));
double b = sum_y / dataModel.size() - a * sum_x / dataModel.size();
return new double[]{a, b};
}
}
运行结果(用到了Apache Echarts可视化):