正态分布拟合对比echarts 折线配置项内容和展示

通过x轴概率和y轴数据拟态标准正态分布,与原图进行对比分析

配置项如下
      //相关详细说明:https://www.cnblogs.com/daxiongblog/p/12679363.html
var formulaCalcByFunc = function(formula, digit) {
    var pow = Math.pow(10, digit);
    return parseInt(formula * pow, 10) / pow;
};

function gaussFunc(x, xMaxi, yMaxi, s) {
    return yMaxi * math.exp(-((x - xMaxi) * (x - xMaxi) / s));
}
/**
* 标准正态分布函数
* @@param x 数据
* @@param mean 平均数
* @@param stdev 标准差
*/
function normalDistributionfun(x, mean, stdev) {
    return (1 / (Math.sqrt(2 * Math.PI) * stdev)) * Math.exp(-1 * ((x - mean) * (x - mean)) / (2 * stdev * stdev));
}

/**第二种方法: 使用标准正态分布函数实现的方法,通过在峰值周围寻找均值
**结果将会偏向原始数据峰值
****/
function calcNormallineDta2(xData, yData) {
            var result = [];
         
            var totalCount = 0;

            var firstMode = 0;//峰值起始位置
            var modeCount = 0;//找到目前数据的峰值
        
            for (var i = 0; i < yData.length;i++) {
                totalCount += yData[i];
                if (yData[i] > modeCount) {
                    modeCount = yData[i];
                    firstMode = i;
                }
             
            }
            //找出出x轴左右范围内的均值(关键代码)
            var mode = 0;
            var modeDuplicates = 0;
        
            var fellOffTop = true;

            for (var j = firstMode; j < yData.length; j ++) {
                if (yData[j] > yData[firstMode] - (yData[firstMode]/10)) {//10:分布线系数
                    mode += j ;
                    modeDuplicates++;
                }
                else {
                    fellOffTop = false;
                    break;
                }
            }

            var fellOffBottom = true;
        
            for (var k=firstMode-1;k>=0;k--) {
                if (yData[k] > yData[firstMode] - (yData[firstMode] / 10)) {//10:分布线系数
                    mode += k;
                    modeDuplicates++;
                }
                else {
                    fellOffBottom = false;
                    break;
                }
            }
            var mean;
            if (fellOffBottom || fellOffTop) {
               
                mean = firstMode;
            }
            else {
                mean = mode/ modeDuplicates;
            }
            //求出标准差
          
            var stdev = 0;
        
            for (var n = 0; n < yData.length;n++) {
                stdev += Math.pow((n - mean), 2) * yData[n];
            }
        
            stdev /= totalCount-1;
        
            stdev = Math.sqrt(stdev);
            //带入正态分布公式
            for (var m = 0; m < yData.length;m++) {
                var probability =normalDistributionfun(m,mean,stdev);
                result.push(Math.round(probability * totalCount*100)/100);
            }
            return result;
        }
      
var yData = [
    //12, 18.5, 37, 49, 66, 96.5, 118.5, 152.5, 215.5, 301.5, 403.5, 561, 876.5, 1328, 2017, 3374, 5478, 8938, 14880, 23522.5, 35697.5, 52651, 74815, 103371, 138536, 179551, 226008.5, 277843, 334386.5, 393973.5, 455601, 519580.5, 587045.5, 656523.5, 726978, 798408.5, 872569.5, 949706, 1022758, 1088846.5, 1149543.5, 1203080.5, 1247561, 1286516.5, 1320628, 1344814, 1357527, 1365572, 1375075.5, 1390487.5, 1407814, 1422297, 1432251.5, 1437508.5, 1437575, 1426377, 1409143, 1381505, 1335454, 1280151.5, 1219327.5, 1151028.5, 1075104, 989740.5, 892589, 784644.5, 678118.5, 579388.5, 486477.5, 401252, 326401.5, 260947.5, 205139.5, 159754, 122746, 94782.5, 73813.5, 57018, 44220, 34231.5, 26245.5, 20156, 15339.5, 11284, 8157, 5945, 4234, 2827.5, 1881, 1235, 772.5, 483.5, 298.5, 177.5, 108, 64.5, 44, 38, 61.5, 47.5, 7
    53, 53, 58.5, 78, 115, 154.5, 200, 300.5, 383.5, 518, 871.5, 1382.5, 2192.5, 3340.5, 5249, 8979.5, 15448, 26225, 44057.5, 71392, 109113, 159006, 224595.5, 307191.5, 405623, 520332, 646965.5, 785170.5, 930962.5, 1078572.5, 1227179.5, 1373870, 1522723.5, 1671622.5, 1812839.5, 1944963, 2068185, 2180604.5, 2280685.5, 2361196.5, 2417123.5, 2457786, 2483891, 2494890, 2496943.5, 2498862.5, 2500857.5, 2500175, 2501485, 2499141, 2492862, 2478390, 2459869.5, 2443707, 2430140, 2421345.5, 2404805, 2377592.5, 2334130, 2263164, 2163510.5, 2031018.5, 1872739.5, 1698482, 1507286, 1306381.5, 1114865.5, 938499, 771654.5, 619227.5, 488654.5, 379699.5, 289925.5, 218837.5, 165510.5, 126806, 97552, 75560, 59062, 46304.5, 36476, 28583, 22280.5, 16965.5, 12631.5, 9265.5, 6629, 4548.5, 3091, 2102.5, 1396.5, 921, 580, 345, 203.5, 137, 87, 46, 27.5, 12, 6
]
var xData = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100"]
var datas2 = [];
var yData2 = [];
var yArr = [];
var xArr = xData.map(n => parseInt(n));
var sumFuc = (s, c) => formulaCalcByFunc(s + c, 6);
var len = xArr.length;
var ysum = yData.reduce(sumFuc, 0);
for (var n = 0; n < yData.length; n++) {
    //var d = (dataArr[i] - mathCalcResult.avg) / mathCalcResult.stdDev;
    var y = yData[n] / ysum;
    yArr.push(y);
}
var avg = math.mean(yArr);

function gaussFit(xOriginal, yOriginal, average) {
    var x = [];
    var y = [];
    // 过滤平滑部分
    for (var i = 0; i < yOriginal.length; i++) { 
        if (yOriginal[i] > average) {
        x.push(xOriginal[i]);
        y.push(yOriginal[i]);
        }
    }
    
    var zMatrix = math.matrix(math.log(y));
    var zMatrixT =zMatrix;

    var xMatrix = math.ones([y.length, 3]);
    //[1,x,x*x]
    for (var j = 0; j < y.length; j++) {
        xMatrix[j][1] = x[j];
        xMatrix[j][2] = x[j] * x[j];
    }
    // 最小二乘法
    var xMatrixT = math.transpose(xMatrix);
    var bMatrix = math.multiply(math.multiply(math.inv(math.multiply(xMatrixT,
        xMatrix)), xMatrixT), zMatrixT);
    // 取值
    var b2 = math.subset(bMatrix, math.index(2));
    var b1 = math.subset(bMatrix, math.index(1));
    var b0 = math.subset(bMatrix, math.index(0));

    var s = -1 / b2;
    var xMaxi = s * b1 / 2;
    var yMaxi = math.exp(b0 + xMaxi * xMaxi / s);

    var yFit = []
    for (var n = 0; n < yOriginal.length; n++) {
        yFit.push(gaussFunc(xOriginal[n], xMaxi, yMaxi, s));
    }

    return yFit;
}
datas2 = gaussFit(xArr, yArr, avg);
for (var k = 0; k < datas2.length; k++) {
    var l = datas2[k] / yArr[k];
    //var d = (dataArr[i] - mathCalcResult.avg) / mathCalcResult.stdDev;
    var y = yData[k] * l;
    yData2.push(y);
}

var colors = ['#7CCD7C', '#d14a61', '#675bba'];
option = {
    color: colors,

    tooltip: {
        trigger: 'axis',
        axisPointer: {
            type: 'cross'
        }
    },
    grid: {
        right: '20%'
    },
    toolbox: {
        feature: {
            dataView: {
                show: true,
                readOnly: false
            },
            restore: {
                show: true
            },
            saveAsImage: {
                show: true
            }
        }
    },
    legend: {
        data: ['原数据', '正态分布']
    },
    xAxis: [{
        type: 'category',
        axisTick: {
            alignWithLabel: true
        },
        data: xData
    }],
    yAxis: [{
            type: 'value',
            name: '原数据',
            position: 'left'

        },
        {
            type: 'value',
            position: 'right'
        }
    ],
    series: [{
            name: '原数据',
            type: 'line',
            animation: false,
            showSymbol: false,
            itemStyle: {
                color: "red"
            },
            data: yData
        },
        {
            name: '正态分布',
            type: 'line',
            smooth: true,
            data: yData2
        }

    ]
};
    
截图如下