mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-11 17:58:41 +00:00
More unit tests and fix statistic
This commit is contained in:
parent
cc904e772a
commit
510842727c
|
|
@ -157,7 +157,7 @@ class Average
|
|||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws phpOMS\Math\Exception\ZeroDevisionException
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
|
@ -309,52 +309,6 @@ class Average
|
|||
return rad2deg(atan2($y, $x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate angle based on time.
|
||||
*
|
||||
* Example: ('08:44:28')
|
||||
*
|
||||
* @param string $time Time
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function timeToAngle(string $time) : float
|
||||
{
|
||||
$parts = explode(':', $time);
|
||||
|
||||
if (count($parts) !== 3) {
|
||||
throw new \Exception('Wrong time format');
|
||||
}
|
||||
|
||||
$sec = ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2];
|
||||
$angle = 360.0 * ($sec / 86400.0);
|
||||
|
||||
return $angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate time based on angle.
|
||||
*
|
||||
* Example: ('08:44:28')
|
||||
*
|
||||
* @param float $angle Angle
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function angleToTime(float $angle) : string
|
||||
{
|
||||
$sec = 86400.0 * $angle / 360.0;
|
||||
$time = sprintf('%02d:%02d:%02d', floor($sec / 3600), floor(($sec % 3600) / 60), $sec % 60);
|
||||
|
||||
return $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the angle mean.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class Basic
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function freaquency(array $values) : array
|
||||
public static function frequency(array $values) : array
|
||||
{
|
||||
$freaquency = [];
|
||||
$sum = 1;
|
||||
|
|
@ -46,8 +46,8 @@ class Basic
|
|||
}
|
||||
|
||||
foreach ($values as $value) {
|
||||
if ($isArray) {
|
||||
$freaquency[] = self::freaquency($value);
|
||||
if (is_array($value)) {
|
||||
$freaquency[] = self::frequency($value);
|
||||
} else {
|
||||
$freaquency[] = $value / $sum;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,11 +59,11 @@ class Correlation
|
|||
$count = count($x);
|
||||
$sum = 0.0;
|
||||
|
||||
for ($i = $k + 1; $i < $count; ++$i) {
|
||||
for ($i = $k; $i < $count; ++$i) {
|
||||
$sum += ($x[$i] - $mean) * ($x[$i - $k] - $mean);
|
||||
}
|
||||
|
||||
return $sum / ($squaredMeanDeviation * count($x));
|
||||
return $sum / ($squaredMeanDeviation * $count);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,40 +71,41 @@ class Correlation
|
|||
*
|
||||
* @param array $autocorrelations Autocorrelations
|
||||
* @param int $h Maximum leg considered
|
||||
* @param int $n Amount of observations
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function boxPierceTest(array $autocorrelations, int $h) : float
|
||||
public static function boxPierceTest(array $autocorrelations, int $h, int $n) : float
|
||||
{
|
||||
$sum = 0;
|
||||
for ($i = 0; $i < $h; ++$i) {
|
||||
$sum += $autocorrelations[$i] ** 2;
|
||||
}
|
||||
|
||||
return count($autocorrelations) * $sum;
|
||||
return $n * $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Box Pierce test (portmanteau test).
|
||||
* Ljung Box test (portmanteau test).
|
||||
*
|
||||
* @param array $autocorrelations Autocorrelations
|
||||
* @param int $h Maximum leg considered
|
||||
* @param int $n Amount of observations
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function ljungBoxTest(array $autocorrelations, int $h) : float
|
||||
public static function ljungBoxTest(array $autocorrelations, int $h, int $n) : float
|
||||
{
|
||||
$count = count($autocorrelations);
|
||||
$sum = 0;
|
||||
$sum = 0;
|
||||
|
||||
for ($i = 0; $i < $h; ++$i) {
|
||||
$sum += 1 / ($count - $i) * $autocorrelations[$i] ** 2;
|
||||
$sum += 1 / ($n - ($i + 1)) * $autocorrelations[$i] ** 2;
|
||||
}
|
||||
|
||||
return $count * ($count + 2) * $sum;
|
||||
return $n * ($n + 2) * $sum;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,14 @@ class MeasureOfDispersion
|
|||
*/
|
||||
public static function standardDeviation(array $values) : float
|
||||
{
|
||||
return sqrt(self::sampleVariance($values));
|
||||
$mean = Average::arithmeticMean($values);
|
||||
$sum = 0.0;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$sum += ($value - $mean) ** 2;
|
||||
}
|
||||
|
||||
return sqrt($sum / (count($values) - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -109,7 +116,7 @@ class MeasureOfDispersion
|
|||
throw new ZeroDevisionException();
|
||||
}
|
||||
|
||||
return $count * self::empiricalVariance($values) / ($count - 1);
|
||||
return self::empiricalVariance($values) * $count / ($count - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -117,7 +124,8 @@ class MeasureOfDispersion
|
|||
*
|
||||
* Example: ([4, 5, 9, 1, 3])
|
||||
*
|
||||
* @param array $values Values
|
||||
* @param array $values Values
|
||||
* @param array $probabilities Probabilities
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
|
|
@ -125,22 +133,23 @@ class MeasureOfDispersion
|
|||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function empiricalVariance(array $values) : float
|
||||
public static function empiricalVariance(array $values, array $probabilities = []) : float
|
||||
{
|
||||
$count = count($values);
|
||||
$count = count($values);
|
||||
$hasProbability = !empty($probabilities);
|
||||
|
||||
if ($count === 0) {
|
||||
throw new ZeroDevisionException();
|
||||
}
|
||||
|
||||
$mean = Average::arithmeticMean($values);
|
||||
$mean = $hasProbability ? Average::weightedAverage($values, $probabilities) : Average::arithmeticMean($values);
|
||||
$sum = 0;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$sum += $value - $mean;
|
||||
foreach ($values as $key => $value) {
|
||||
$sum += ($hasProbability ? $probabilities[$key] : 1) * ($value - $mean) ** 2;
|
||||
}
|
||||
|
||||
return $sum / ($count - 1);
|
||||
return $hasProbability ? $sum : $sum / $count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -216,6 +225,27 @@ class MeasureOfDispersion
|
|||
return $sum / count($x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mean absolute deviation.
|
||||
*
|
||||
* @param array $x Values
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public static function meanAbsoluteDeviation(array $x) : float
|
||||
{
|
||||
$mean = Average::arithmeticMean($x);
|
||||
$sum = 0.0;
|
||||
|
||||
foreach ($x as $xi) {
|
||||
$sum += abs($xi - $mean);
|
||||
}
|
||||
|
||||
return $sum / count($x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get squared mean deviation.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -21,4 +21,66 @@ class AverageTest extends \PHPUnit\Framework\TestCase
|
|||
{
|
||||
self::assertEquals(-3 / 2, Average::averageDatasetChange([6, 7, 6, 3, 0]));
|
||||
}
|
||||
|
||||
public function testMean()
|
||||
{
|
||||
self::assertEquals(4, Average::arithmeticMean([1, 2, 3, 4, 5, 6, 7]), '', 0.01);
|
||||
|
||||
self::assertEquals(69 / 20, Average::weightedAverage(
|
||||
[1, 2, 3, 4, 5, 6, 7],
|
||||
[0.1, 0.2, 0.3, 0.1, 0.2, 0.05, 0.05]
|
||||
), '', 0.01);
|
||||
|
||||
self::assertEquals(3.3800151591413, Average::geometricMean([1, 2, 3, 4, 5, 6, 7]), '', 0.01);
|
||||
self::assertEquals(2.6997245179063, Average::harmonicMean([1, 2, 3, 4, 5, 6, 7]), '', 0.01);
|
||||
|
||||
self::assertEquals(-90, Average::angleMean([90.0, 180.0, 270.0, 360.0]), '', 0.01);
|
||||
self::assertEquals(9.999999999999977, Average::angleMean([370.0]), '', 0.01);
|
||||
|
||||
self::assertEquals(270, Average::angleMean2([90.0, 180.0, 270.0, 360.0]), '', 0.01);
|
||||
self::assertEquals(9.999999999999977, Average::angleMean2([370.0]), '', 0.01);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException phpOMS\Math\Matrix\Exception\InvalidDimensionException
|
||||
*/
|
||||
public function testInvalidWeightedAverageDimension()
|
||||
{
|
||||
Average::weightedAverage([1, 2, 3, 4, 5, 6, 7], [0.1, 0.2, 0.3, 0.1, 0.2, 0.05]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException phpOMS\Math\Exception\ZeroDevisionException
|
||||
*/
|
||||
public function testInvalidArithmeticMeanZeroDevision()
|
||||
{
|
||||
Average::arithmeticMean([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException phpOMS\Math\Exception\ZeroDevisionException
|
||||
*/
|
||||
public function testInvalidGeometricMean()
|
||||
{
|
||||
Average::geometricMean([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException phpOMS\Math\Exception\ZeroDevisionException
|
||||
*/
|
||||
public function testInvalidHarmonicMean()
|
||||
{
|
||||
Average::harmonicMean([1, 2, 3, 0, 5, 6, 7]);
|
||||
}
|
||||
|
||||
public function testMode()
|
||||
{
|
||||
self::assertEquals(2, Average::mode([1, 2, 2, 3, 4, 4, 2]), '', 0.01);
|
||||
}
|
||||
|
||||
public function testMedia()
|
||||
{
|
||||
self::assertEquals(4, Average::median([1, 2, 3, 4, 5, 6, 7]), '', 0.01);
|
||||
self::assertEquals(3.5, Average::median([1, 2, 3, 4, 5, 6]), '', 0.01);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,16 @@ use phpOMS\Math\Statistic\Basic;
|
|||
|
||||
class BasicTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testPlaceholder()
|
||||
public function testFrequency()
|
||||
{
|
||||
self::markTestIncomplete();
|
||||
self::assertEquals(
|
||||
[1 / 10, 2 / 10, 3 / 10, 4 / 10],
|
||||
Basic::frequency([1, 2, 3, 4])
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1 / 10, 2 / 10, 3 / 10, [1 / 6, 2 / 6, 3 / 6], 4 / 10],
|
||||
Basic::frequency([1, 2, 3, [1, 2, 3], 4])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,45 @@ use phpOMS\Math\Statistic\Correlation;
|
|||
|
||||
class CorrelationTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testPlaceholder()
|
||||
public function testBravisPersonCorrelationCoefficient()
|
||||
{
|
||||
self::markTestIncomplete();
|
||||
self::assertEquals(
|
||||
0.8854,
|
||||
Correlation::bravaisPersonCorrelationCoefficient(
|
||||
[1, 2, 3, 4, 5, 6, 7],
|
||||
[3, 4, 5, 9, 7, 8, 9]
|
||||
), '', 0.01
|
||||
);
|
||||
}
|
||||
|
||||
public function testAutocorrelationCoefficient()
|
||||
{
|
||||
$data = [
|
||||
1, 20, 31, 8, 40, 41, 46, 89, 72, 45, 81, 93,
|
||||
41, 63, 17, 96, 68, 27, 41, 17, 26, 75, 63, 93,
|
||||
18, 93, 80, 36, 4, 23, 81, 47, 61, 27, 13, 25,
|
||||
51, 20, 65, 45, 87, 68, 36, 31, 79, 7, 95, 37
|
||||
];
|
||||
|
||||
self::assertEquals(0.022, Correlation::autocorrelationCoefficient($data, 1), '', 0.01);
|
||||
self::assertEquals(0.098, Correlation::autocorrelationCoefficient($data, 2), '', 0.01);
|
||||
}
|
||||
|
||||
public function testPortmanteauTest()
|
||||
{
|
||||
$data = [
|
||||
1, 20, 31, 8, 40, 41, 46, 89, 72, 45, 81, 93,
|
||||
41, 63, 17, 96, 68, 27, 41, 17, 26, 75, 63, 93,
|
||||
18, 93, 80, 36, 4, 23, 81, 47, 61, 27, 13, 25,
|
||||
51, 20, 65, 45, 87, 68, 36, 31, 79, 7, 95, 37
|
||||
];
|
||||
|
||||
$correlations = [];
|
||||
for ($i = 0; $i < 24; $i++) {
|
||||
$correlations[] = Correlation::autocorrelationCoefficient($data, $i + 1);
|
||||
}
|
||||
|
||||
self::assertEquals(16.46, Correlation::boxPierceTest($correlations, 24, 48), '', 0.01);
|
||||
self::assertEquals(24.92, Correlation::ljungBoxTest($correlations, 24, 48), '', 0.01);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,4 +21,70 @@ class MeasureOfDispersionTest extends \PHPUnit\Framework\TestCase
|
|||
{
|
||||
self::assertEquals((float) (9 - 1), MeasureOfDispersion::range([4, 5, 9, 1, 3]));
|
||||
}
|
||||
|
||||
public function testStandardDeviation()
|
||||
{
|
||||
self::assertEquals(2.160246, MeasureOfDispersion::standardDeviation([1, 2, 3, 4, 5, 6, 7]), '', 0.01);
|
||||
}
|
||||
|
||||
public function testEmpiricalCovariance()
|
||||
{
|
||||
self::assertEquals(
|
||||
4.667,
|
||||
MeasureOfDispersion::empiricalCovariance(
|
||||
[1, 2, 3, 4, 5, 6, 7],
|
||||
[3, 4, 5, 9, 7, 8, 9]
|
||||
), '', 0.01
|
||||
);
|
||||
}
|
||||
|
||||
public function testVariance()
|
||||
{
|
||||
self::assertEquals(6219.9, MeasureOfDispersion::sampleVariance([3, 21, 98, 203, 17, 9]), '', 0.01);
|
||||
self::assertEquals(5183.25, MeasureOfDispersion::empiricalVariance([3, 21, 98, 203, 17, 9]), '', 0.01);
|
||||
}
|
||||
|
||||
public function testDeviation()
|
||||
{
|
||||
self::assertEquals(0.0, MeasureOfDispersion::meanDeviation([3, 4, 5, 9, 7, 8, 9]), '', 0.01);
|
||||
self::assertEquals(2.0816, MeasureOfDispersion::meanAbsoluteDeviation([3, 4, 5, 9, 7, 8, 9]), '', 0.01);
|
||||
self::assertEquals((12.96 + 2.56 + 0.36 + 5.76 + 11.56) / 5, MeasureOfDispersion::squaredMeanDeviation([1, 3, 4, 7, 8]), '', 0.01);
|
||||
}
|
||||
|
||||
public function testEmpiricalVariationCoefficient()
|
||||
{
|
||||
self::assertEquals(0.5400, MeasureOfDispersion::empiricalVariationCoefficient([1, 2, 3, 4, 5, 6, 7]), '', 0.01);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException phpOMS\Math\Exception\ZeroDevisionException
|
||||
*/
|
||||
public function testInvalidEmpiricalCovariance()
|
||||
{
|
||||
MeasureOfDispersion::empiricalCovariance([], []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException phpOMS\Math\Matrix\Exception\InvalidDimensionException
|
||||
*/
|
||||
public function testInvalidEmpiricalCovarianceDimension()
|
||||
{
|
||||
MeasureOfDispersion::empiricalCovariance([1, 2, 3, 4], [1, 2, 3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException phpOMS\Math\Exception\ZeroDevisionException
|
||||
*/
|
||||
public function testInvalidSampleVariance()
|
||||
{
|
||||
MeasureOfDispersion::sampleVariance([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException phpOMS\Math\Exception\ZeroDevisionException
|
||||
*/
|
||||
public function testInvalidEmpiricalVariance()
|
||||
{
|
||||
MeasureOfDispersion::empiricalVariance([]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user