package com.moral.util;
|
|
import java.util.*;
|
|
/**
|
* @ClassName ComprehensiveIndexUtils
|
* @Description 综合指数计算工具类
|
* @Author 陈凯裕
|
* @Date 2021/9/27 9:40
|
* @Version TODO
|
**/
|
public class ComprehensiveIndexUtils {
|
|
/**
|
* @Description: 获取月综合指数,参数为日数据的集合,map为每日的数据
|
* @Param: [datas]
|
* @return: Double
|
* @Author: 陈凯裕
|
* @Date: 2021/9/27
|
*/
|
public static Double monthData(List<Map<String, Object>> datas) {
|
//计算各污染物的统计量浓度值
|
Map<String, Double> CValueMap = calCValue(datas);
|
if (CValueMap == null)
|
return null;
|
Double CSO2 = CValueMap.get("CSO2");
|
Double CNO2 = CValueMap.get("CNO2");
|
Double CPM25 = CValueMap.get("CPM25");
|
Double CPM10 = CValueMap.get("CPM10");
|
Double CCO = CValueMap.get("CCO");
|
Double CO3 = CValueMap.get("CO3");
|
//S开头为污染物年均值二级标准(当污染物是CO时,采用日均值二级标准。当污染是O3时,采用八小时均值二级标准)
|
//数据来源GB 3095-2012
|
Double SSO2 = 60d;
|
Double SNO2 = 40d;
|
Double SPM25 = 35d;
|
Double SPM10 = 70d;
|
Double SCO = 4d;
|
Double SO3 = 160d;
|
//计算污染物单项指数
|
Double ISO2 = CSO2 / SSO2;
|
Double INO2 = CNO2 / SNO2;
|
Double IPM25 = CPM25 / SPM25;
|
Double IPM10 = CPM10 / SPM10;
|
Double ICO = CCO / SCO;
|
Double IO3 = CO3 / SO3;
|
//计算综合指数
|
Double comprehensiveIndex = MathUtils.add(ISO2, INO2);
|
comprehensiveIndex = MathUtils.add(comprehensiveIndex, IPM25);
|
comprehensiveIndex = MathUtils.add(comprehensiveIndex, IPM10);
|
comprehensiveIndex = MathUtils.add(comprehensiveIndex, ICO);
|
comprehensiveIndex = MathUtils.add(comprehensiveIndex, IO3);
|
comprehensiveIndex = AmendUtils.sciCal(comprehensiveIndex, 2);
|
return comprehensiveIndex;
|
}
|
|
/**
|
* @Description: 计算各因子浓度值
|
* SO2 NO2 PM10 PM2.5为月均浓度,CO取日均值的第九十五百分位,O3取日最大八小时值的第九十百分位
|
* @Param: [datas]
|
* @return: java.util.Map<java.lang.String, java.lang.Object>
|
* @Author: 陈凯裕
|
* @Date: 2021/9/27
|
*/
|
private static Map<String, Double> calCValue(List<Map<String, Object>> datas) {
|
//定义浓度值
|
Double CSO2;//SO2统计量浓度值
|
Double CNO2;//NO2统计量浓度值
|
Double CPM10;//PM10统计量浓度值
|
Double CPM25;//PM25统计量浓度值
|
Double CCO;//CO统计量浓度值
|
Double CO3;//O3统计量浓度值
|
//计算SO2 NO2 PM10 PM2.5月均值
|
Double SO2Sum = 0d;
|
Double NO2Sum = 0d;
|
Double PM10Sum = 0d;
|
Double PM25Sum = 0d;
|
Double SO2Num = 0d;
|
Double NO2Num = 0d;
|
Double PM10Num = 0d;
|
Double PM25Num = 0d;
|
for (Map<String, Object> data : datas) {
|
Object SO2 = data.get("a21026");
|
Object NO2 = data.get("a21004");
|
Object PM10 = data.get("a34002");
|
Object PM25 = data.get("a34004");
|
if (SO2 != null) {
|
SO2Num++;
|
SO2Sum = MathUtils.add(SO2Sum, Double.valueOf(SO2.toString()));
|
}
|
if (NO2 != null) {
|
NO2Num++;
|
NO2Sum = MathUtils.add(NO2Sum, Double.valueOf(NO2.toString()));
|
}
|
if (PM10 != null) {
|
PM10Num++;
|
PM10Sum = MathUtils.add(PM10Sum, Double.valueOf(PM10.toString()));
|
}
|
if (PM25 != null) {
|
PM25Num++;
|
PM25Sum = MathUtils.add(PM25Sum, Double.valueOf(PM25.toString()));
|
}
|
|
}
|
CSO2 = SO2Sum / SO2Num;
|
CNO2 = NO2Sum / NO2Num;
|
CPM10 = PM10Sum / PM10Num;
|
CPM25 = PM25Sum / PM25Num;
|
if (CSO2 == 0d || CNO2 == 0d || CPM10 == 0d || CPM25 == 0d)
|
return null;
|
|
/*计算CO统计量浓度值*/
|
//获取CO从小到大排序的集合
|
List<Double> COs = getSensorAsc(datas, "a21005");
|
//取第95百分位
|
if (COs.size() == 0)
|
return null;
|
Double COIndexd = COs.size() * 0.95;
|
int COIndex = new Double(Math.ceil(COIndexd)).intValue();
|
CCO = COs.get(COIndex - 1);
|
|
/*计算O3统计量浓度*/
|
//获取O3日八小时最大值从小到大排序的结婚
|
List<Double> O3s = getSensorAsc(datas, "a05024");
|
//取第90百分位
|
if (O3s.size() == 0)
|
return null;
|
Double O3Indexd = O3s.size() * 0.9;
|
int O3Index = new Double(Math.ceil(O3Indexd)).intValue();
|
CO3 = O3s.get(O3Index - 1);
|
|
Map<String, Double> result = new HashMap<>();
|
result.put("CSO2", CSO2);
|
result.put("CNO2", CNO2);
|
result.put("CPM25", CPM25);
|
result.put("CPM10", CPM10);
|
result.put("CCO", CCO);
|
result.put("CO3", CO3);
|
return result;
|
}
|
|
/**
|
* @Description: 获取因子的升序排序集合
|
* @Param: [datas]
|
* @return: java.util.List<java.lang.Double>
|
* @Author: 陈凯裕
|
* @Date: 2021/9/27
|
*/
|
private static List<Double> getSensorAsc(List<Map<String, Object>> datas, String sensor) {
|
List<Double> result = new ArrayList<>();
|
datas.forEach(value -> {
|
Object o = value.get(sensor);
|
if (o != null)
|
result.add(Double.valueOf(o.toString()));
|
});
|
Collections.sort(result, new Comparator<Double>() {
|
@Override
|
public int compare(Double o1, Double o2) {
|
return new Double(o1 - o2).intValue();
|
}
|
});
|
return result;
|
}
|
|
/**
|
* @Description: 获取日综合指数,参数为日六参数据
|
* @Param: [data]
|
* @return: Double
|
*/
|
public static Double dailyData(Map<String, Object> data) {
|
if (data == null)
|
return null;
|
Double CPM25 = (Double) data.get("pm2_5");
|
Double CPM10 = (Double) data.get("pm10");
|
Double CSO2 = (Double) data.get("so2");
|
Double CNO2 = (Double) data.get("no2");
|
Double CCO = (Double) data.get("co");
|
Double CO3 = (Double) data.get("o3");
|
//S开头为污染物年均值二级标准(当污染物是CO时,采用日均值二级标准。当污染是O3时,采用八小时均值二级标准)
|
//数据来源GB 3095-2012
|
Double SSO2 = 60d;
|
Double SNO2 = 40d;
|
Double SPM25 = 35d;
|
Double SPM10 = 70d;
|
Double SCO = 4d;
|
Double SO3 = 160d;
|
//计算污染物单项指数
|
Double ISO2 = CSO2 / SSO2;
|
Double INO2 = CNO2 / SNO2;
|
Double IPM25 = CPM25 / SPM25;
|
Double IPM10 = CPM10 / SPM10;
|
Double ICO = CCO / SCO;
|
Double IO3 = CO3 / SO3;
|
//计算综合指数
|
Double comprehensiveIndex = MathUtils.add(ISO2, INO2);
|
comprehensiveIndex = MathUtils.add(comprehensiveIndex, IPM25);
|
comprehensiveIndex = MathUtils.add(comprehensiveIndex, IPM10);
|
comprehensiveIndex = MathUtils.add(comprehensiveIndex, ICO);
|
comprehensiveIndex = MathUtils.add(comprehensiveIndex, IO3);
|
comprehensiveIndex = AmendUtils.sciCal(comprehensiveIndex, 2);
|
return comprehensiveIndex;
|
}
|
|
}
|