66
77class Stat
88{
9- final public const MEDIAN_TYPE_LOW = ' LOW ' ;
9+ final public const MEDIAN_TYPE_LOW = " LOW " ;
1010
11- final public const MEDIAN_TYPE_HIGH = ' HIGH ' ;
11+ final public const MEDIAN_TYPE_HIGH = " HIGH " ;
1212
13- final public const MEDIAN_TYPE_MIDDLE = ' MIDDLE ' ;
13+ final public const MEDIAN_TYPE_MIDDLE = " MIDDLE " ;
1414
1515 /**
1616 * Count the element in the array
@@ -39,21 +39,23 @@ public static function mean(array $data): int|float|null
3939 {
4040 $ sum = 0 ;
4141 if (self ::count ($ data ) === 0 ) {
42- throw new InvalidDataInputException (' The data must not be empty. ' );
42+ throw new InvalidDataInputException (" The data must not be empty. " );
4343 }
44- if (array_filter ($ data , 'is_string ' ) !== []) {
45- throw new InvalidDataInputException ('The data array contains a string. ' );
44+ if (array_filter ($ data , "is_string " ) !== []) {
45+ throw new InvalidDataInputException (
46+ "The data array contains a string. " ,
47+ );
4648 }
4749 $ sum = array_sum ($ data );
4850
4951 return $ sum / self ::count ($ data );
5052 }
5153
5254 /**
53- * Calculate the float number arithmetic mean of a float numbers dataset with optional weights and precision.
54- *
55- * Supports both unweighted and weighted means. Automatically casts values to float.
56- * Returns `null` if the input data is empty.
55+ * Calculate the float number arithmetic mean of a float numbers dataset with optional weights and precision.
56+ *
57+ * Supports both unweighted and weighted means. Automatically casts values to float.
58+ * Returns `null` if the input data is empty.
5759 *
5860 * @param array<float> $data Array of floating numbers
5961 * @param null|array<float> $weights Optional array of weights (same length as $data).
@@ -62,17 +64,20 @@ public static function mean(array $data): int|float|null
6264 *
6365 * @throws InvalidDataInputException if the data is empty
6466 */
65- public static function fmean (array $ data , array |null $ weights = null , int |null $ precision = null ): float |null
66- {
67+ public static function fmean (
68+ array $ data ,
69+ ?array $ weights = null ,
70+ ?int $ precision = null ,
71+ ): ?float {
6772 $ sum = 0 ;
6873 $ count = self ::count ($ data );
6974 if ($ count === 0 ) {
70- throw new InvalidDataInputException (' The data must not be empty. ' );
75+ throw new InvalidDataInputException (" The data must not be empty. " );
7176 }
7277
7378 // Unweighted mean
7479 if ($ weights === null ) {
75- $ sum = array_sum (array_map (' floatval ' , $ data ));
80+ $ sum = array_sum (array_map (" floatval " , $ data ));
7681 $ count = count ($ data );
7782 if ($ precision ) {
7883 return round ($ sum / $ count , $ precision );
@@ -82,7 +87,9 @@ public static function fmean(array $data, array|null $weights = null, int|null $
8287
8388 // Check lengths
8489 if ($ count !== count ($ weights )) {
85- throw new InvalidDataInputException ('The data and weights must be the same length ' );
90+ throw new InvalidDataInputException (
91+ "The data and weights must be the same length " ,
92+ );
8693 }
8794
8895 $ weightedSum = 0.0 ;
@@ -94,7 +101,9 @@ public static function fmean(array $data, array|null $weights = null, int|null $
94101 }
95102
96103 if ($ weightTotal == 0 ) {
97- throw new InvalidDataInputException ('The sum of weights must be non-zero ' );
104+ throw new InvalidDataInputException (
105+ "The sum of weights must be non-zero " ,
106+ );
98107 }
99108
100109 if ($ precision ) {
@@ -111,21 +120,24 @@ public static function fmean(array $data, array|null $weights = null, int|null $
111120 * @return mixed median of the data
112121 * @throws InvalidDataInputException if the data is empty
113122 */
114- public static function median (array $ data , string $ medianType = self ::MEDIAN_TYPE_MIDDLE ): mixed
115- {
123+ public static function median (
124+ array $ data ,
125+ string $ medianType = self ::MEDIAN_TYPE_MIDDLE ,
126+ ): mixed {
116127 sort ($ data );
117128 $ count = self ::count ($ data );
118129 if ($ count === 0 ) {
119- throw new InvalidDataInputException (' The data must not be empty. ' );
130+ throw new InvalidDataInputException (" The data must not be empty. " );
120131 }
121- $ index = (int ) floor ($ count / 2 ); // cache the index
122- if (($ count & 1 ) !== 0 ) { // count is odd
132+ $ index = (int ) floor ($ count / 2 ); // cache the index
133+ if (($ count & 1 ) !== 0 ) {
134+ // count is odd
123135 return $ data [$ index ];
124136 }
125137
126138 // count is even
127139 return match ($ medianType ) {
128- self ::MEDIAN_TYPE_LOW => ( $ data [$ index - 1 ]) ,
140+ self ::MEDIAN_TYPE_LOW => $ data [$ index - 1 ],
129141 self ::MEDIAN_TYPE_HIGH => $ data [$ index ],
130142 default => ($ data [$ index - 1 ] + $ data [$ index ]) / 2 ,
131143 };
@@ -180,7 +192,7 @@ public static function mode(array $data, bool $multimode = false): mixed
180192 {
181193 $ frequencies = Freq::frequencies ($ data );
182194 if ($ frequencies === []) {
183- throw new InvalidDataInputException (' The data must not be empty. ' );
195+ throw new InvalidDataInputException (" The data must not be empty. " );
184196 }
185197 $ sameMode = true ;
186198 foreach ($ frequencies as $ value ) {
@@ -212,7 +224,7 @@ public static function mode(array $data, bool $multimode = false): mixed
212224 *
213225 * @return mixed[]|null array of the most common data points or null, if all elements occurs once
214226 */
215- public static function multimode (array $ data ): array | null
227+ public static function multimode (array $ data ): ? array
216228 {
217229 return self ::mode ($ data , true );
218230 }
@@ -227,27 +239,31 @@ public static function multimode(array $data): array|null
227239 *
228240 * @throws InvalidDataInputException if number of quantiles is less than 1, or the data size is less than 2
229241 */
230- public static function quantiles (array $ data , int $ n = 4 , ?int $ round = null ): array
231- {
242+ public static function quantiles (
243+ array $ data ,
244+ int $ n = 4 ,
245+ ?int $ round = null ,
246+ ): array {
232247 $ count = self ::count ($ data );
233248 if ($ count < 2 || $ n < 1 ) {
234249 throw new InvalidDataInputException (
235- ' The size of the data must be greater than 2 and the number of quantiles must be greater than 1. ' ,
250+ " The size of the data must be greater than 2 and the number of quantiles must be greater than 1. " ,
236251 );
237252 }
238253
239254 sort ($ data );
240255 $ m = $ count + 1 ;
241256 $ result = [];
242257 foreach (range (1 , $ n - 1 ) as $ i ) {
243- $ j = floor ($ i * $ m / $ n );
258+ $ j = ( int ) floor (( $ i * $ m) / $ n );
244259 if ($ j < 1 ) {
245260 $ j = 1 ;
246261 } elseif ($ j > $ count - 1 ) {
247262 $ j = $ count - 1 ;
248263 }
249264 $ delta = $ i * $ m - $ j * $ n ;
250- $ interpolated = ($ data [$ j - 1 ] * ($ n - $ delta ) + $ data [$ j ] * $ delta ) / $ n ;
265+ $ interpolated
266+ = ($ data [$ j - 1 ] * ($ n - $ delta ) + $ data [$ j ] * $ delta ) / $ n ;
251267 $ result [] = Math::round ($ interpolated , $ round );
252268 }
253269
@@ -321,7 +337,7 @@ public static function pvariance(array $data, ?int $round = null): float
321337 {
322338 $ num_of_elements = self ::count ($ data );
323339 if ($ num_of_elements == 0 ) {
324- throw new InvalidDataInputException (' The data must not be empty. ' );
340+ throw new InvalidDataInputException (" The data must not be empty. " );
325341 }
326342 $ sumSquareDifferences = 0.0 ;
327343 $ average = self ::mean ($ data );
@@ -332,7 +348,7 @@ public static function pvariance(array $data, ?int $round = null): float
332348 $ sumSquareDifferences += ($ i - $ average ) ** 2 ;
333349 }
334350
335- return Math::round ($ sumSquareDifferences / ( $ num_of_elements) , $ round );
351+ return Math::round ($ sumSquareDifferences / $ num_of_elements , $ round );
336352 }
337353
338354 /**
@@ -365,7 +381,9 @@ public static function variance(array $data, ?int $round = null): float
365381 {
366382 $ num_of_elements = self ::count ($ data );
367383 if ($ num_of_elements <= 1 ) {
368- throw new InvalidDataInputException ('The data size must be greater than 1. ' );
384+ throw new InvalidDataInputException (
385+ "The data size must be greater than 1. " ,
386+ );
369387 }
370388 $ sumSquareDifferences = 0.0 ;
371389 $ average = self ::mean ($ data );
@@ -376,7 +394,10 @@ public static function variance(array $data, ?int $round = null): float
376394 $ sumSquareDifferences += ($ i - $ average ) ** 2 ;
377395 }
378396
379- return Math::round ($ sumSquareDifferences / ($ num_of_elements - 1 ), $ round );
397+ return Math::round (
398+ $ sumSquareDifferences / ($ num_of_elements - 1 ),
399+ $ round ,
400+ );
380401 }
381402
382403 /**
@@ -394,7 +415,7 @@ public static function geometricMean(array $data, ?int $round = null): float
394415 {
395416 $ count = self ::count ($ data );
396417 if ($ count === 0 ) {
397- throw new InvalidDataInputException (' The data must not be empty. ' );
418+ throw new InvalidDataInputException (" The data must not be empty. " );
398419 }
399420 $ product = 1 ;
400421 foreach ($ data as $ value ) {
@@ -415,12 +436,15 @@ public static function geometricMean(array $data, ?int $round = null): float
415436 *
416437 * @throws InvalidDataInputException if the data is empty
417438 */
418- public static function harmonicMean (array $ data , ?array $ weights = null , ?int $ round = null ): float
419- {
439+ public static function harmonicMean (
440+ array $ data ,
441+ ?array $ weights = null ,
442+ ?int $ round = null ,
443+ ): float {
420444 $ sum = 0 ;
421445 $ count = self ::count ($ data );
422446 if ($ count === 0 ) {
423- throw new InvalidDataInputException (' The data must not be empty. ' );
447+ throw new InvalidDataInputException (" The data must not be empty. " );
424448 }
425449 $ sumWeigth = 0 ;
426450 foreach ($ data as $ key => $ value ) {
@@ -451,12 +475,12 @@ public static function covariance(array $x, array $y): false|float
451475 $ countY = count ($ y );
452476 if ($ countX !== $ countY ) {
453477 throw new InvalidDataInputException (
454- ' Covariance requires that both inputs have same number of data points. ' ,
478+ " Covariance requires that both inputs have same number of data points. " ,
455479 );
456480 }
457481 if ($ countX < 2 ) {
458482 throw new InvalidDataInputException (
459- ' Covariance requires at least two data points. ' ,
483+ " Covariance requires at least two data points. " ,
460484 );
461485 }
462486 $ meanX = self ::mean ($ x );
@@ -467,18 +491,18 @@ public static function covariance(array $x, array $y): false|float
467491 $ valueX = $ x [$ pos ];
468492 if (!is_numeric ($ valueX )) {
469493 throw new InvalidDataInputException (
470- ' Covariance requires numeric data points. ' ,
494+ " Covariance requires numeric data points. " ,
471495 );
472496 }
473497 $ valueY = $ y [$ pos ];
474498 if (!is_numeric ($ valueY )) {
475499 throw new InvalidDataInputException (
476- ' Covariance requires numeric data points. ' ,
500+ " Covariance requires numeric data points. " ,
477501 );
478502 }
479503 $ diffX = $ valueX - $ meanX ;
480504 $ diffY = $ valueY - $ meanY ;
481- $ add += ( $ diffX * $ diffY) ;
505+ $ add += $ diffX * $ diffY ;
482506 }
483507
484508 // covariance for sample: N - 1
@@ -506,12 +530,12 @@ public static function correlation(array $x, array $y): false|float
506530 $ countY = count ($ y );
507531 if ($ countX !== $ countY ) {
508532 throw new InvalidDataInputException (
509- ' Correlation requires that both inputs have same number of data points. ' ,
533+ " Correlation requires that both inputs have same number of data points. " ,
510534 );
511535 }
512536 if ($ countX < 2 ) {
513537 throw new InvalidDataInputException (
514- ' Correlation requires at least two data points. ' ,
538+ " Correlation requires at least two data points. " ,
515539 );
516540 }
517541 $ meanX = self ::mean ($ x );
@@ -530,7 +554,7 @@ public static function correlation(array $x, array $y): false|float
530554 $ b = sqrt ($ bx * $ by );
531555 if ($ b == 0 ) {
532556 throw new InvalidDataInputException (
533- ' Correlation, at least one of the inputs is constant. ' ,
557+ " Correlation, at least one of the inputs is constant. " ,
534558 );
535559 }
536560
@@ -552,12 +576,12 @@ public static function linearRegression(array $x, array $y): array
552576 $ countY = count ($ y );
553577 if ($ countX !== $ countY ) {
554578 throw new InvalidDataInputException (
555- ' Linear regression requires that both inputs have same number of data points. ' ,
579+ " Linear regression requires that both inputs have same number of data points. " ,
556580 );
557581 }
558582 if ($ countX < 2 ) {
559583 throw new InvalidDataInputException (
560- ' Linear regression requires at least two data points. ' ,
584+ " Linear regression requires at least two data points. " ,
561585 );
562586 }
563587 $ sumX = array_sum ($ x );
@@ -566,17 +590,17 @@ public static function linearRegression(array $x, array $y): array
566590 $ sumXY = 0 ;
567591
568592 foreach ($ x as $ key => $ value ) {
569- $ sumXY += ( $ value * $ y [$ key ]) ;
570- $ sumXX += ( $ value * $ value) ;
593+ $ sumXY += $ value * $ y [$ key ];
594+ $ sumXX += $ value * $ value ;
571595 }
572- $ denominator = (( $ countX * $ sumXX) - ( $ sumX * $ sumX)) ;
596+ $ denominator = $ countX * $ sumXX - $ sumX * $ sumX ;
573597 if ($ denominator === 0 ) {
574598 throw new InvalidDataInputException (
575- ' Linear regression, the inputs is constant. ' ,
599+ " Linear regression, the inputs is constant. " ,
576600 );
577601 }
578- $ slope = (( $ countX * $ sumXY) - ( $ sumX * $ sumY) ) / $ denominator ;
579- $ intercept = ($ sumY - ( $ slope * $ sumX) ) / $ countX ;
602+ $ slope = ($ countX * $ sumXY - $ sumX * $ sumY ) / $ denominator ;
603+ $ intercept = ($ sumY - $ slope * $ sumX ) / $ countX ;
580604
581605 return [$ slope , $ intercept ];
582606 }
0 commit comments