Implementation of the CHITEST() statistical function (#1960)
* Implementation of the CHITEST() statistical function * A couple of additional edge case tests (rows = 1, columns = 1)
This commit is contained in:
parent
a34dd71cce
commit
67fec4e3fc
|
|
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Implemented the CHITEST() Statistical function.
|
||||||
- Support for ActiveSheet and SelectedCells in the ODS Reader and Writer. [PR #1908](https://github.com/PHPOffice/PhpSpreadsheet/pull/1908)
|
- Support for ActiveSheet and SelectedCells in the ODS Reader and Writer. [PR #1908](https://github.com/PHPOffice/PhpSpreadsheet/pull/1908)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
||||||
|
|
@ -518,12 +518,12 @@ class Calculation
|
||||||
],
|
],
|
||||||
'CHITEST' => [
|
'CHITEST' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Functions::class, 'DUMMY'],
|
'functionCall' => [Statistical\Distributions\ChiSquared::class, 'test'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'CHISQ.TEST' => [
|
'CHISQ.TEST' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Functions::class, 'DUMMY'],
|
'functionCall' => [Statistical\Distributions\ChiSquared::class, 'test'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'CHOOSE' => [
|
'CHOOSE' => [
|
||||||
|
|
|
||||||
|
|
@ -82,4 +82,45 @@ class ChiSquared
|
||||||
|
|
||||||
return $newtonRaphson->execute($probability);
|
return $newtonRaphson->execute($probability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function test($actual, $expected)
|
||||||
|
{
|
||||||
|
$rows = count($actual);
|
||||||
|
$actual = Functions::flattenArray($actual);
|
||||||
|
$expected = Functions::flattenArray($expected);
|
||||||
|
$columns = count($actual) / $rows;
|
||||||
|
|
||||||
|
$countActuals = count($actual);
|
||||||
|
$countExpected = count($expected);
|
||||||
|
if ($countActuals !== $countExpected || $countActuals === 1) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = 0.0;
|
||||||
|
for ($i = 0; $i < $countActuals; ++$i) {
|
||||||
|
if ($expected[$i] == 0.0) {
|
||||||
|
return Functions::DIV0();
|
||||||
|
} elseif ($expected[$i] < 0.0) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
$result += (($actual[$i] - $expected[$i]) ** 2) / $expected[$i];
|
||||||
|
}
|
||||||
|
|
||||||
|
$degrees = self::degrees($rows, $columns);
|
||||||
|
|
||||||
|
$result = self::distribution($result, $degrees);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function degrees(int $rows, int $columns): int
|
||||||
|
{
|
||||||
|
if ($rows === 1) {
|
||||||
|
return $columns - 1;
|
||||||
|
} elseif ($columns === 1) {
|
||||||
|
return $rows - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($columns - 1) * ($rows - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class ChiTestTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @dataProvider providerCHITEST
|
||||||
|
*
|
||||||
|
* @param mixed $expectedResult
|
||||||
|
* @param mixed $actual
|
||||||
|
* @param mixed $expected
|
||||||
|
*/
|
||||||
|
public function testCHITEST($expectedResult, $actual, $expected): void
|
||||||
|
{
|
||||||
|
$result = Statistical\Distributions\ChiSquared::test($actual, $expected);
|
||||||
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerCHITEST()
|
||||||
|
{
|
||||||
|
return require 'tests/data/Calculation/Statistical/CHITEST.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
0.0152703571482,
|
||||||
|
[[112, 76], [85, 95]],
|
||||||
|
[[100, 85], [70, 90]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.000308192027,
|
||||||
|
[[58, 35], [11, 25], [10, 23]],
|
||||||
|
[[45.35, 47.65], [17.56, 18.44], [16.09, 16.91]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.015888560447,
|
||||||
|
[[58], [11], [10]],
|
||||||
|
[[45.35], [17.56], [16.09]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0.008682970191,
|
||||||
|
[[58, 35]],
|
||||||
|
[[45.35, 47.65]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#NUM!',
|
||||||
|
[[58, 11], [10, 35], [25]],
|
||||||
|
[[45.35, 17.56], [16.09, 47.65], [18.44, 16.91]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#DIV/0!',
|
||||||
|
[[112, 76], [85, 95]],
|
||||||
|
[[100, 0], [70, 90]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#NUM!',
|
||||||
|
[[112, 76], [85, 95]],
|
||||||
|
[[100, 85], [-70, 90]],
|
||||||
|
],
|
||||||
|
];
|
||||||
Loading…
Reference in New Issue