标签归档:趋势线

PHP 拟合函数计算趋势线

    // 拟合算法(最小二乘法)
    // 输入: $values = [2, 3, 5, 4, 7, 8, 3, 2, 6];
    // 输出: $values = [3.578, 3.794, 4.011, 4.228, 4.444, 4.661, 4.878, 5.094, 5.311];
    // 斜率(正切值): k = y / x;   =>   5.311 - 3.578 / 9 = 0.1925,最终结果是负无穷 -> 0 -> 正无穷
    // k=0 说明无斜率,与X轴平行, k=1说明斜度为45度,大于1说明斜度大于45度(分正负)
    // atan(k)获取弧度角,弧度换算为角度:atan(k) * (180 / M_PI);
    public function trendLine(array $values)
    {
        $n = count($values);
        $sumX = 0;
        $sumY = 0.0;
        $sumXX = 0;
        $sumXY = 0.0;
        for($i = 1; $i <= $n; $i++) {
            $sumX += $i;
            $sumY += $values[$i - 1];
            $sumXX += $i * $i;
            $sumXY += $i * $values[$i - 1];
        }
        // 求a,b
        $b = ($n * $sumXY - $sumX * $sumY) / ($n * $sumXX - $sumX * $sumX);
        $a = ($sumY - $b * $sumX) / $n;
        // 返回趋势线y值
        $ys = [];
        for($i = 1; $i <= $n; $i++) {
            $ys[$i - 1] = round($b * $i + $a, 3);
        }
        // 斜率(正切值)
        $slope = ($ys[$n -1] - $ys[0]) / $n;
        // 弧度
        $radians = atan($slope);
        // 角度(1度 = 180 / M_PI = 57.297弧度)
        $degree = $radians * 57.297;

        return [
            'slope' => $slope,
            'radians' => $radians,
            'degree' => $degree,
            'values' => $ys
        ];
    }

至于最小二乘法的公式和原理可以搜索一下。根据这个计算的结果,可以得到一条直线的趋势线,通常我们顺便计算一下斜率以及夹角大小(弧度角和角度)。

图表工具 – jQuery插件jqplot

jQuery插件jqplot这个画图表的工具功能很齐全,个人觉得它虽然不是最好的画图表的工具,但是它提供了根据当前数据自动画趋势图的功能,是我去使用它的主要原因。
jqplot-graph
经过研究,它只能画直线的趋势线(而不能像在Excel中的那样画多项式趋势线),不过目前暂时还没有发现哪个JS或PHP工具提供了画趋势线的…

这个工具的使用,刚开始是比较困难的,参数很多,搞不清楚参数有什么作用,当然可以看文档说明,然后多去尝试。也可以对着官方提供的例子去看。这个工具本身提供了很多的插件,特别是渲染器,不同的渲染器提供了不同的选项,而且它画图的时候使用的是canvas元素。当使用了某个渲染器时必须把对应的JS插件加载进来,否则,就无法工作。以下是一份简要说明:

$(document).ready(function () {

    var s1 = [<?php echo implode(', ', $ods);?>];
    var s2 = [<?php echo implode(', ', $ods_);?>];

    plot = $.jqplot("chart1", [s1, s2], {
    	// 是否动画显示
        animate: true,
        //animateReplot: true,
        
        // --指定可选颜色,线条等可用的颜色
    	seriesColors: [ "#4bb2c5", "#c5b47f", "#EAA228", "#579575" ],
        // --标题 也可以使用另一只方式
    	title: "--- xxx统计 ---",
    	//title: {
        //    text: '',
        //    show: true,
        //},
    	// --
    	// stackSeries: false

    	// -- 设置轴线的默认值
    	// 1 三个概念, Label渲染器(Label), 刻度线的渲染器(选项),刻度渲染器(选项)
    	// 2 不同的渲染器会有不同的选项,对应有不同的选项,不同的轴线的默认值从axesDefaults中继承
    	// 3 轴线可定义最大最小值,指定刻度值...
        axesDefaults: {
            show: false,
            min: null, 				// 刻度最小值
            max: null,				// 刻度最大值
            pad: 0,					
            ticks: [],				// 固定刻度,默认时自动确定的,有多个Y轴时,如果指定,最好元素一样多
            numberTicks: undefined,
            renderer: $.jqplot.LinearAxisRenderer, 	// 画轴时使用的渲染器
            rendererOptions: {},					// 画轴时使用的渲染器的选项
            tickOptions: {
                mark: 'outside',
                showMark: true,
                showGridline: true,					// 是否显示网格线
                markSize: 4,
                show: true,
                showLabel: true,					// 是否显示Label
                formatString: '',					// 刻度值的格式化字符串
            },
            showTicks: false,
            showTickMarks: false,
        },
        // --具体的轴定义,每个轴的可用参数跟axesDefaults一样
        axes: {
            // X轴
            xaxis: {
                 // 轴线渲染器  默认使用继承的线条渲染器,这里的X轴要使用分类轴渲染器
	           	 renderer: $.jqplot.CategoryAxisRenderer,
	           	 // 轴的标签显示,渲染器使用Canvas轴标签渲染器
	             label: 'X轴',
	             labelRenderer: $.jqplot.CanvasAxisLabelRenderer,
	             // 刻度的渲染器,这里是要转角度
	             tickRenderer: $.jqplot.CanvasAxisTickRenderer,
	             tickOptions: {
	            	 showGridline: false,
	                 angle: -30
	             }
            },
            // Y轴(左)
            yaxis: {
                // 可以指定有效的刻度值
            	//ticks: [],
                tickOptions: {
                	//轴的网格线是否显示
                	//showGridline: false,
                    formatString: "%'d"
                },
                rendererOptions: {
                    forceTickAt0: true
                }
            },
            // Y轴(右)
            y2axis: {
            	//ticks: [],
                tickOptions: {
                    //轴的网格线是否显示
                	showGridline: false,
                    formatString: "%.2f%"
                },
                rendererOptions: {
                    // 多个轴时,刻度是否对齐
                    alignTicks: true,
                    forceTickAt0: true
                }
            }
        },
        
        // 线条的默认值
        seriesDefaults: {
            show: true,     // wether to render the series.
            xaxis: 'xaxis', // either 'xaxis' or 'x2axis'.
            yaxis: 'yaxis', // either 'yaxis' or 'y2axis'.
            label: '',      // label to use in the legend for this line.
            color: '',      // CSS color spec to use for the line.  Determined automatically.
            lineWidth: 1.5, // Width of the line in pixels.
            shadow: true,   // show shadow or not.
            shadowAngle: 45,    // angle (degrees) of the shadow, clockwise from x axis.
            shadowOffset: 1.25, // offset from the line of the shadow.
            shadowDepth: 3,     // Number of strokes to make when drawing shadow.  Each
                                // stroke offset by shadowOffset from the last.
            shadowAlpha: 0.1,   // Opacity of the shadow.
            showLine: true,     // whether to render the line segments or not.
            showMarker: true,   // render the data point markers or not.
            fill: false,        // fill under the line,
            fillAndStroke: false,       // *stroke a line at top of fill area.
            fillColor: undefined,       // *custom fill color for filled lines (default is line color).
            fillAlpha: undefined,       // *custom alpha to apply to fillColor.
            renderer: $.jqplot.LineRenderer,    // renderer used to draw the series.
            rendererOptions: {}, 				// options passed to the renderer.  LineRenderer has no options.

            // 折线图上的点
            markerRenderer: $.jqplot.MarkerRenderer,
            markerOptions: {
                show: true,             // wether to show data point markers.
                style: 'filledSquare',  // circle, diamond, square, filledCircle.
                                        // filledDiamond or filledSquare.
                lineWidth: 1,       // width of the stroke drawing the marker.
                size: 9,            // size (diameter, edge length, etc.) of the marker.
                //color: '#666666', // color of marker, set to color of line by default.
                shadow: true,       // wether to draw shadow on marker or not.
                shadowAngle: 45,    // angle of the shadow.  Clockwise from x axis.
                shadowOffset: 1,    // offset from the line of the shadow,
                shadowDepth: 3,     // Number of strokes to make when drawing shadow.  Each stroke
                                    // offset by shadowOffset from the last.
                shadowAlpha: 0.07   // Opacity of the shadow
            },
            
            // 趋势线  需要jqplot.trendline.js插件
            trendline: {
                // 是否显示
                show: true,
                // 趋势线的颜色
                color: '#000',
                // label
                label: '趋势线',
                // 类型,线条  和 指数  'linear', 'exponential' or 'exp'
                type: 'exp',
                // 趋势线宽度
                lineWidth: 1,
                // 趋势线的阴影设置
                shadow: false,
                shadowAngle: 45,
                shadowOffset: 1.5,
                shadowDepth: 3,            
                shadowAlpha: 0.07 
            }
        },
        
        series:[
       		{
            	label: "XXX订单总量",
                // 是否显示点上的值
                pointLabels: {
                	show: true
             	},
             	// 鼠标放到点上时是否显示值
             	showHighlight: false,
                rendererOptions: {
                    // 动画显示速度
                	animation: {
                    	speed: 2000
                 	}
              	},
              	trendline: {
              		label: '-- 趋势线',
                }
            },
            {
                label: "XXX缺货率",
                // 是否显示点上的值
                pointLabels: {
                    show: true
                },
                // 鼠标放到点上时是否显示值
                showHighlight: false,
                yaxis: 'y2axis',
                rendererOptions: {
                    animation: {
                        speed: 2500
                    }
                },
              	trendline: {
              		label: '-- 趋势线',
                }
            }
        ],

        // 自动抓取线了Label和颜色
        legend: {
            show: true,
            //这个Renderer可以点击对应的指示标,显示和隐藏对应的线,但是无法显示趋势线 XX
            //renderer: $.jqplot.EnhancedLegendRenderer,
            //rendererOptions: {
            //    numberRows: 4
            //},
            placement: 'outsideGrid',
            location: 'e'
        },
        grid: {
            drawGridLines: true,        // wether to draw lines across the grid or not.
            gridLineColor: '#cccccc',   // *Color of the grid lines.
            background: '#fffdff',      // CSS color spec for background color of grid.
            borderColor: '#999999',     // CSS color spec for border around grid.
            borderWidth: 1.0,           // pixel width of border around grid.
            shadow: true,               // draw a shadow for grid.
            shadowAngle: 45,            // angle of the shadow.  Clockwise from x axis.
            shadowOffset: 2.5,          // offset from the line of the shadow.
            shadowWidth: 3,             // width of the stroke for the shadow.
            shadowDepth: 3,             // Number of strokes to make when drawing shadow.
                                        // Each stroke offset by shadowOffset from the last.
            shadowAlpha: 0.07,          // Opacity of the shadow
            renderer: $.jqplot.CanvasGridRenderer,  // renderer to use to draw the grid.
            rendererOptions: {}         // options to pass to the renderer.  Note, the default
                                        // CanvasGridRenderer takes no additional options.
        }, 
	// 鼠标放入图中指针的样式
        cursor: {
            // 指针样式
            style: 'pointer',     // A CSS spec for the cursor type to change the
                                    // cursor to when over plot.
            // 是否显示
            show: true,
            // 是否可以放大
            zoom: false,
            looseZoom: false,
            // 是否显示提示框 跟随鼠标 位置 偏移...
            showTooltip: true,
            followMouse: false,
            tooltipLocation: 'se', 
            tooltipOffset: 6,
            showTooltipGridPosition: false,
            showTooltipUnitPosition: true,
            tooltipFormatString: '%.4P',
            useAxesFormatters: true,
            tooltipAxesGroups: [],
        },
        highlighter: {
            show: true, 
            showLabel: true, 
            tooltipAxes: 'y',
            sizeAdjust: 7.5 , tooltipLocation : 'ne'
        },
    });
});

jQuery jqplot Demo
jQuery jqplot Demo 下载

永久链接:http://blog.ifeeline.com/1706.html