如何为不规则时间图创建平均线?

我正在使用HighCharts构建不规则的时间图,目前看起来像这样:

图形

而且我想知道是否有可能为三条(或可能更多的未来)线创建一条“平均”线。

它将开始跟随蓝线,然后更接近1月中旬的绿线等。

目前我正在使用的代码如下:

$('#chart').highcharts({ chart: { type: 'spline' }, title: { text: '' }, xAxis: { type: 'datetime' }, yAxis: { title: { text: '' } } series: [{ name: 'Line 1', data: [ [Date.UTC(2014,0,16), 173.33], [Date.UTC(2014,0,23), 163.33], [Date.UTC(2014,0,30), 137.67], [Date.UTC(2014,1,6), 176.33], [Date.UTC(2014,1,13), 178.67], [Date.UTC(2014,1,27), 167.33], ], color: 'purple' }, { name: 'Line 2', data: [ [Date.UTC(2014,0,11), 156.33], [Date.UTC(2014,1,15), 167.67], ], color: 'green' }, { name: 'Line 3', data: [ [Date.UTC(2014,0,1), 135], [Date.UTC(2014,0,5), 146.33], [Date.UTC(2014,0,27), 146.75], ], color: 'blue' }] }); 

您所描述的内容称为趋势或回归线 。 Highcharts没有内置的添加这些线条的能力,但数学并不太难(而且,自己做的更有趣)。 我用最小二乘的线性回归编写了最简单的例子。

 ///////////////////// //utility functions// //////////////////// // linear regression // given array of x values and array of y values // returns rV object with slope/intercept lineFit = function(xs, ys, rV){ rV.slope = 0.0; rV.intercept = 0.0; rV.rSquared = 1.0; // assume perfection if (xs.length < 2) { return false; } if (xs.Count != ys.Count) { return false; } var N = xs.length; var sumX = sumFunc(xs,null); var sumY = sumFunc(ys,null); var funcSq = function(i){return (i*i);} var funcSq2 = function(i,j){return (i*j);} var sumXx = sumFunc(xs, funcSq); var sumYy = sumFunc(ys, funcSq); var sumXy = sumFunc(zip(xs,ys),funcSq2); rV.slope = ((N * sumXy) - (sumX * sumY)) / (N * sumXx - (sumX*sumX)); rV.intercept = (sumY - rV.slope * sumX) / N; rV.rSquared = Math.abs((rV.slope * (sumXy - (sumX * sumY) / N)) / (sumYy - ((sumY * sumY) / N))); return true; } // sums arrays with optional function transformation sumFunc = function(arr, func){ var total = 0; $.each(arr, function(i,k){ if ($.isArray(k)){ if (func == null){ k = k[0] + k[1]; }else{ k = func(k[0],k[1]); } } else { if (func != null){ k = func(k); } } total += k; }); return total; } // python style zip function // to pair to array together zip = function(arr1,arr2) { var rV = []; for(var i=0; i 

lineFit函数将返回具有斜率和截距属性的rV对象(通过引用)。 之后,您可以向Highcharts添加一条线,其中包含良好的老式y = slope * x + intercept ,minX是回归线的起始值,maxX是结束值。

  { name: 'Regression Line', data: [[minX, reg.slope * minX + reg.intercept], [maxX, reg.slope * maxX + reg.intercept]], color: 'red', marker:{enabled:false}, lineWidth: 5 } 

在这里工作小提琴 。

在此处输入图像描述

根据Mark的答案提供的想法,我编写了一些代码来生成自定义的第四行,使用来自所有三行的数据,并计算每个点的所需值。

我的新代码如下:

  line1 = [ [Date.UTC(2014,0,16), 173.33], [Date.UTC(2014,0,23), 163.33], [Date.UTC(2014,0,30), 137.67], [Date.UTC(2014,1,6), 176.33], [Date.UTC(2014,1,13), 178.67], [Date.UTC(2014,1,27), 167.33], ]; line2 = [ [Date.UTC(2014,0,11), 156.33], [Date.UTC(2014,1,15), 167.67], ]; line3 = [ [Date.UTC(2014,0,1), 135], [Date.UTC(2014,0,5), 146.33], [Date.UTC(2014,0,27), 146.75], [Date.UTC(2014,2,2), 168.75] ]; function average(array, index) { sum = array[0][1]; for(var i = 1; i <= index; i++) { sum += array[i][1]; } value = sum / (index + 1); return parseFloat(value.toFixed(2)); } // Make a fourth line with all of the data points for the other // three lines, sorted by date all_lines = line1.concat(line2).concat(line3); all_lines.sort(function(a, b) { return a[0] - b[0]}); // Calculate the value for each data point in the fourth line - // the average of all the values before it average_line = []; for(var i = 0; i < all_lines.length; i++) { average_line.push([all_lines[i][0], average(all_lines, i)]) } $('#chart').highcharts({ chart: { type: 'spline' }, title: { text: '', }, xAxis: { type: 'datetime' }, yAxis: { title: { text: '' } }, legend: { layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0 }, series: [{ name: 'Line 1', data: line1, color: 'purple' }, { name: 'Line 2', data: line2, color: 'green' }, { name: 'Line 3', data: line3, color: 'blue' }, { name: 'Average', data: average_line, color: 'red' }] }); 

现在看起来的图形(蓝线上有一个额外的数据点)是:

在此处输入图像描述