|
|
@@ -0,0 +1,158 @@
|
|
|
+package com.jjt.utils;
|
|
|
+
|
|
|
+import org.apache.commons.math3.distribution.NormalDistribution;
|
|
|
+import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
|
|
|
+import org.apache.commons.math3.stat.inference.KolmogorovSmirnovTest;
|
|
|
+
|
|
|
+import java.util.Arrays;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 正态性检验工具类
|
|
|
+ *
|
|
|
+ * @author wukai
|
|
|
+ * @date 2025-10-23 15:18:50
|
|
|
+ */
|
|
|
+public class NormalityUtil {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Shapiro-Wilk正态性检验(需要实现或使用其他库)
|
|
|
+ * 这里使用Apache Commons Math的替代方法
|
|
|
+ */
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Kolmogorov-Smirnov正态性检验
|
|
|
+ *
|
|
|
+ * @param data 待检验数据
|
|
|
+ * @return p-value
|
|
|
+ */
|
|
|
+ public static double kolmogorovSmirnovTest(double[] data) {
|
|
|
+ KolmogorovSmirnovTest ksTest = new KolmogorovSmirnovTest();
|
|
|
+
|
|
|
+ // 计算数据的均值和标准差
|
|
|
+ DescriptiveStatistics stats = new DescriptiveStatistics(data);
|
|
|
+ double mean = stats.getMean();
|
|
|
+ double std = stats.getStandardDeviation();
|
|
|
+
|
|
|
+ // 创建正态分布对象
|
|
|
+ NormalDistribution normalDist = new NormalDistribution(mean, std);
|
|
|
+
|
|
|
+ // 执行KS检验
|
|
|
+ return ksTest.kolmogorovSmirnovTest(normalDist, data);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Anderson-Darling正态性检验
|
|
|
+ *
|
|
|
+ * @param data 待检验数据
|
|
|
+ * @return 检验统计量
|
|
|
+ */
|
|
|
+ public static double andersonDarlingTest(double[] data) {
|
|
|
+ double[] sortedData = data.clone();
|
|
|
+ Arrays.sort(sortedData);
|
|
|
+
|
|
|
+ int n = sortedData.length;
|
|
|
+ DescriptiveStatistics stats = new DescriptiveStatistics(data);
|
|
|
+ double mean = stats.getMean();
|
|
|
+ double std = stats.getStandardDeviation();
|
|
|
+
|
|
|
+ double sum = 0.0;
|
|
|
+ for (int i = 0; i < n; i++) {
|
|
|
+ double z = (sortedData[i] - mean) / std;
|
|
|
+ double f = cumulativeNormalDistribution(z);
|
|
|
+ double term = (2 * (i + 1) - 1) * (Math.log(f) + Math.log(1 - cumulativeNormalDistribution(sortedData[n - 1 - i] - mean) / std));
|
|
|
+ sum += term;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -n - sum / n;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 累积正态分布函数
|
|
|
+ */
|
|
|
+ private static double cumulativeNormalDistribution(double x) {
|
|
|
+ NormalDistribution normal = new NormalDistribution();
|
|
|
+ return normal.cumulativeProbability(x);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 综合正态性检验
|
|
|
+ *
|
|
|
+ * @param data 待检验数据
|
|
|
+ * @param alpha 显著性水平
|
|
|
+ */
|
|
|
+ public static String comprehensiveNormalityUtil(double[] data, double alpha) {
|
|
|
+ System.out.println("=== 正态性检验结果 ===");
|
|
|
+ System.out.printf("样本数量: %d\n", data.length);
|
|
|
+ System.out.printf("均值: %.4f\n", new DescriptiveStatistics(data).getMean());
|
|
|
+ System.out.printf("标准差: %.4f\n", new DescriptiveStatistics(data).getStandardDeviation());
|
|
|
+
|
|
|
+ // KS检验
|
|
|
+ double ksPValue = kolmogorovSmirnovTest(data);
|
|
|
+ System.out.printf("Kolmogorov-Smirnov检验 p-value: %.6f\n", ksPValue);
|
|
|
+ System.out.printf("KS检验结果: %s\n", ksPValue > alpha ? "符合正态分布" : "不符合正态分布");
|
|
|
+
|
|
|
+ // Anderson-Darling检验
|
|
|
+ double adStatistic = andersonDarlingTest(data);
|
|
|
+ System.out.printf("Anderson-Darling检验统计量: %.6f\n", adStatistic);
|
|
|
+
|
|
|
+ // 使用Apache Commons Math的检验工具
|
|
|
+ try {
|
|
|
+ // 为以下内容(假设采用KS检验代替):
|
|
|
+ double shapiroWilkPValue = kolmogorovSmirnovTest(data);
|
|
|
+ System.out.printf("模拟 Shapiro-Wilk 检验 p-value: %.6f\n", shapiroWilkPValue);
|
|
|
+ System.out.printf("检验结果: %s\n", shapiroWilkPValue > alpha ? "符合正态分布" : "不符合正态分布");
|
|
|
+ return shapiroWilkPValue > alpha ? "符合正态分布" : "不符合正态分布";
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return "校验失败";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成正态分布测试数据
|
|
|
+ */
|
|
|
+ public static double[] generateNormalData(int size, double mean, double std) {
|
|
|
+ double[] data = new double[size];
|
|
|
+ NormalDistribution normal = new NormalDistribution(mean, std);
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ data[i] = normal.sample();
|
|
|
+ }
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成均匀分布测试数据(非正态)
|
|
|
+ */
|
|
|
+ public static double[] generateUniformData(int size, double min, double max) {
|
|
|
+ double[] data = new double[size];
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ data[i] = min + Math.random() * (max - min);
|
|
|
+ }
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ // 生成测试数据
|
|
|
+ double[] normalData = NormalityUtil.generateNormalData(100, 0, 1);
|
|
|
+ double[] uniformData = NormalityUtil.generateUniformData(100, 0, 1);
|
|
|
+
|
|
|
+ // 显著性水平
|
|
|
+ double alpha = 0.05;
|
|
|
+
|
|
|
+ System.out.println("正态分布数据检验:");
|
|
|
+ NormalityUtil.comprehensiveNormalityUtil(normalData, alpha);
|
|
|
+
|
|
|
+ System.out.println("\n均匀分布数据检验:");
|
|
|
+ NormalityUtil.comprehensiveNormalityUtil(uniformData, alpha);
|
|
|
+
|
|
|
+ // 使用真实数据示例
|
|
|
+ double[] sampleData = {
|
|
|
+ 1.2, 2.3, 0.8, 1.5, 2.1, 1.8, 0.9, 1.3, 2.0, 1.7,
|
|
|
+ 1.1, 2.2, 1.6, 0.7, 1.9, 1.4, 2.4, 1.0, 0.6, 2.5
|
|
|
+ };
|
|
|
+
|
|
|
+ System.out.println("\n真实数据检验:");
|
|
|
+ NormalityUtil.comprehensiveNormalityUtil(sampleData, alpha);
|
|
|
+ }
|
|
|
+}
|