1: <?php
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: class PHPExcel_Best_Fit
37: {
38: 39: 40: 41: 42:
43: protected $_error = False;
44:
45: 46: 47: 48: 49:
50: protected $_bestFitType = 'undetermined';
51:
52: 53: 54: 55: 56:
57: protected $_valueCount = 0;
58:
59: 60: 61: 62: 63:
64: protected $_xValues = array();
65:
66: 67: 68: 69: 70:
71: protected $_yValues = array();
72:
73: 74: 75: 76: 77:
78: protected $_adjustToZero = False;
79:
80: 81: 82: 83: 84:
85: protected $_yBestFitValues = array();
86:
87: protected $_goodnessOfFit = 1;
88:
89: protected $_stdevOfResiduals = 0;
90:
91: protected $_covariance = 0;
92:
93: protected $_correlation = 0;
94:
95: protected $_SSRegression = 0;
96:
97: protected $_SSResiduals = 0;
98:
99: protected $_DFResiduals = 0;
100:
101: protected $_F = 0;
102:
103: protected $_slope = 0;
104:
105: protected $_slopeSE = 0;
106:
107: protected $_intersect = 0;
108:
109: protected $_intersectSE = 0;
110:
111: protected $_Xoffset = 0;
112:
113: protected $_Yoffset = 0;
114:
115:
116: public function getError() {
117: return $this->_error;
118: }
119:
120:
121: public function getBestFitType() {
122: return $this->_bestFitType;
123: }
124:
125:
126: 127: 128: 129: 130: 131:
132: public function getValueOfYForX($xValue) {
133: return False;
134: }
135:
136:
137: 138: 139: 140: 141: 142:
143: public function getValueOfXForY($yValue) {
144: return False;
145: }
146:
147:
148: 149: 150: 151: 152:
153: public function getXValues() {
154: return $this->_xValues;
155: }
156:
157:
158: 159: 160: 161: 162: 163:
164: public function getEquation($dp=0) {
165: return False;
166: }
167:
168:
169: 170: 171: 172: 173: 174:
175: public function getSlope($dp=0) {
176: if ($dp != 0) {
177: return round($this->_slope,$dp);
178: }
179: return $this->_slope;
180: }
181:
182:
183: 184: 185: 186: 187: 188:
189: public function getSlopeSE($dp=0) {
190: if ($dp != 0) {
191: return round($this->_slopeSE,$dp);
192: }
193: return $this->_slopeSE;
194: }
195:
196:
197: 198: 199: 200: 201: 202:
203: public function getIntersect($dp=0) {
204: if ($dp != 0) {
205: return round($this->_intersect,$dp);
206: }
207: return $this->_intersect;
208: }
209:
210:
211: 212: 213: 214: 215: 216:
217: public function getIntersectSE($dp=0) {
218: if ($dp != 0) {
219: return round($this->_intersectSE,$dp);
220: }
221: return $this->_intersectSE;
222: }
223:
224:
225: 226: 227: 228: 229: 230:
231: public function getGoodnessOfFit($dp=0) {
232: if ($dp != 0) {
233: return round($this->_goodnessOfFit,$dp);
234: }
235: return $this->_goodnessOfFit;
236: }
237:
238:
239: public function getGoodnessOfFitPercent($dp=0) {
240: if ($dp != 0) {
241: return round($this->_goodnessOfFit * 100,$dp);
242: }
243: return $this->_goodnessOfFit * 100;
244: }
245:
246:
247: 248: 249: 250: 251: 252:
253: public function getStdevOfResiduals($dp=0) {
254: if ($dp != 0) {
255: return round($this->_stdevOfResiduals,$dp);
256: }
257: return $this->_stdevOfResiduals;
258: }
259:
260:
261: public function getSSRegression($dp=0) {
262: if ($dp != 0) {
263: return round($this->_SSRegression,$dp);
264: }
265: return $this->_SSRegression;
266: }
267:
268:
269: public function getSSResiduals($dp=0) {
270: if ($dp != 0) {
271: return round($this->_SSResiduals,$dp);
272: }
273: return $this->_SSResiduals;
274: }
275:
276:
277: public function getDFResiduals($dp=0) {
278: if ($dp != 0) {
279: return round($this->_DFResiduals,$dp);
280: }
281: return $this->_DFResiduals;
282: }
283:
284:
285: public function getF($dp=0) {
286: if ($dp != 0) {
287: return round($this->_F,$dp);
288: }
289: return $this->_F;
290: }
291:
292:
293: public function getCovariance($dp=0) {
294: if ($dp != 0) {
295: return round($this->_covariance,$dp);
296: }
297: return $this->_covariance;
298: }
299:
300:
301: public function getCorrelation($dp=0) {
302: if ($dp != 0) {
303: return round($this->_correlation,$dp);
304: }
305: return $this->_correlation;
306: }
307:
308:
309: public function getYBestFitValues() {
310: return $this->_yBestFitValues;
311: }
312:
313:
314: protected function _calculateGoodnessOfFit($sumX,$sumY,$sumX2,$sumY2,$sumXY,$meanX,$meanY, $const) {
315: $SSres = $SScov = $SScor = $SStot = $SSsex = 0.0;
316: foreach($this->_xValues as $xKey => $xValue) {
317: $bestFitY = $this->_yBestFitValues[$xKey] = $this->getValueOfYForX($xValue);
318:
319: $SSres += ($this->_yValues[$xKey] - $bestFitY) * ($this->_yValues[$xKey] - $bestFitY);
320: if ($const) {
321: $SStot += ($this->_yValues[$xKey] - $meanY) * ($this->_yValues[$xKey] - $meanY);
322: } else {
323: $SStot += $this->_yValues[$xKey] * $this->_yValues[$xKey];
324: }
325: $SScov += ($this->_xValues[$xKey] - $meanX) * ($this->_yValues[$xKey] - $meanY);
326: if ($const) {
327: $SSsex += ($this->_xValues[$xKey] - $meanX) * ($this->_xValues[$xKey] - $meanX);
328: } else {
329: $SSsex += $this->_xValues[$xKey] * $this->_xValues[$xKey];
330: }
331: }
332:
333: $this->_SSResiduals = $SSres;
334: $this->_DFResiduals = $this->_valueCount - 1 - $const;
335:
336: if ($this->_DFResiduals == 0.0) {
337: $this->_stdevOfResiduals = 0.0;
338: } else {
339: $this->_stdevOfResiduals = sqrt($SSres / $this->_DFResiduals);
340: }
341: if (($SStot == 0.0) || ($SSres == $SStot)) {
342: $this->_goodnessOfFit = 1;
343: } else {
344: $this->_goodnessOfFit = 1 - ($SSres / $SStot);
345: }
346:
347: $this->_SSRegression = $this->_goodnessOfFit * $SStot;
348: $this->_covariance = $SScov / $this->_valueCount;
349: $this->_correlation = ($this->_valueCount * $sumXY - $sumX * $sumY) / sqrt(($this->_valueCount * $sumX2 - pow($sumX,2)) * ($this->_valueCount * $sumY2 - pow($sumY,2)));
350: $this->_slopeSE = $this->_stdevOfResiduals / sqrt($SSsex);
351: $this->_intersectSE = $this->_stdevOfResiduals * sqrt(1 / ($this->_valueCount - ($sumX * $sumX) / $sumX2));
352: if ($this->_SSResiduals != 0.0) {
353: if ($this->_DFResiduals == 0.0) {
354: $this->_F = 0.0;
355: } else {
356: $this->_F = $this->_SSRegression / ($this->_SSResiduals / $this->_DFResiduals);
357: }
358: } else {
359: if ($this->_DFResiduals == 0.0) {
360: $this->_F = 0.0;
361: } else {
362: $this->_F = $this->_SSRegression / $this->_DFResiduals;
363: }
364: }
365: }
366:
367:
368: protected function _leastSquareFit($yValues, $xValues, $const) {
369:
370: $x_sum = array_sum($xValues);
371: $y_sum = array_sum($yValues);
372: $meanX = $x_sum / $this->_valueCount;
373: $meanY = $y_sum / $this->_valueCount;
374: $mBase = $mDivisor = $xx_sum = $xy_sum = $yy_sum = 0.0;
375: for($i = 0; $i < $this->_valueCount; ++$i) {
376: $xy_sum += $xValues[$i] * $yValues[$i];
377: $xx_sum += $xValues[$i] * $xValues[$i];
378: $yy_sum += $yValues[$i] * $yValues[$i];
379:
380: if ($const) {
381: $mBase += ($xValues[$i] - $meanX) * ($yValues[$i] - $meanY);
382: $mDivisor += ($xValues[$i] - $meanX) * ($xValues[$i] - $meanX);
383: } else {
384: $mBase += $xValues[$i] * $yValues[$i];
385: $mDivisor += $xValues[$i] * $xValues[$i];
386: }
387: }
388:
389:
390:
391: $this->_slope = $mBase / $mDivisor;
392:
393:
394:
395: if ($const) {
396: $this->_intersect = $meanY - ($this->_slope * $meanX);
397: } else {
398: $this->_intersect = 0;
399: }
400:
401: $this->_calculateGoodnessOfFit($x_sum,$y_sum,$xx_sum,$yy_sum,$xy_sum,$meanX,$meanY,$const);
402: }
403:
404:
405: 406: 407: 408: 409: 410: 411:
412: function __construct($yValues, $xValues=array(), $const=True) {
413:
414: $nY = count($yValues);
415: $nX = count($xValues);
416:
417:
418: if ($nX == 0) {
419: $xValues = range(1,$nY);
420: $nX = $nY;
421: } elseif ($nY != $nX) {
422:
423: $this->_error = True;
424: return False;
425: }
426:
427: $this->_valueCount = $nY;
428: $this->_xValues = $xValues;
429: $this->_yValues = $yValues;
430: }
431:
432: }
433: