Start work on refactoring the last of the Excel Statistical functions (#2033)
* Refactoring the last of the Excel Statistical functions
This commit is contained in:
parent
160ae59751
commit
e4973fa041
|
|
@ -1085,11 +1085,6 @@ parameters:
|
||||||
count: 1
|
count: 1
|
||||||
path: src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php
|
path: src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Binary operation \"\\-\" between float\\|int and float\\|string results in an error\\.$#"
|
|
||||||
count: 4
|
|
||||||
path: src/PhpSpreadsheet/Calculation/Statistical.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\:\\:MAXIFS\\(\\) should return float but returns float\\|string\\|null\\.$#"
|
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Statistical\\:\\:MAXIFS\\(\\) should return float but returns float\\|string\\|null\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
|
|
||||||
|
|
@ -848,7 +848,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'DEVSQ' => [
|
'DEVSQ' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'DEVSQ'],
|
'functionCall' => [Statistical\Deviations::class, 'sumSquares'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'DGET' => [
|
'DGET' => [
|
||||||
|
|
@ -1185,7 +1185,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'GAUSS' => [
|
'GAUSS' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'GAUSS'],
|
'functionCall' => [Statistical\Distributions\StandardNormal::class, 'gauss'],
|
||||||
'argumentCount' => '1',
|
'argumentCount' => '1',
|
||||||
],
|
],
|
||||||
'GCD' => [
|
'GCD' => [
|
||||||
|
|
@ -1195,7 +1195,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'GEOMEAN' => [
|
'GEOMEAN' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'GEOMEAN'],
|
'functionCall' => [Statistical\Averages\Mean::class, 'geometric'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'GESTEP' => [
|
'GESTEP' => [
|
||||||
|
|
@ -1215,7 +1215,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'HARMEAN' => [
|
'HARMEAN' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'HARMEAN'],
|
'functionCall' => [Statistical\Averages\Mean::class, 'harmonic'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'HEX2BIN' => [
|
'HEX2BIN' => [
|
||||||
|
|
@ -1529,12 +1529,12 @@ class Calculation
|
||||||
],
|
],
|
||||||
'KURT' => [
|
'KURT' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'KURT'],
|
'functionCall' => [Statistical\Deviations::class, 'kurtosis'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'LARGE' => [
|
'LARGE' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'LARGE'],
|
'functionCall' => [Statistical\Size::class, 'large'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'LCM' => [
|
'LCM' => [
|
||||||
|
|
@ -2071,7 +2071,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'RANK.EQ' => [
|
'RANK.EQ' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'RANK'],
|
'functionCall' => [Statistical\Percentiles::class, 'RANK'],
|
||||||
'argumentCount' => '2,3',
|
'argumentCount' => '2,3',
|
||||||
],
|
],
|
||||||
'RATE' => [
|
'RATE' => [
|
||||||
|
|
@ -2218,7 +2218,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'SKEW' => [
|
'SKEW' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'SKEW'],
|
'functionCall' => [Statistical\Deviations::class, 'skew'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'SKEW.P' => [
|
'SKEW.P' => [
|
||||||
|
|
@ -2238,7 +2238,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'SMALL' => [
|
'SMALL' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'SMALL'],
|
'functionCall' => [Statistical\Size::class, 'small'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'SORT' => [
|
'SORT' => [
|
||||||
|
|
@ -2263,7 +2263,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'STANDARDIZE' => [
|
'STANDARDIZE' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'STANDARDIZE'],
|
'functionCall' => [Statistical\Standardize::class, 'execute'],
|
||||||
'argumentCount' => '3',
|
'argumentCount' => '3',
|
||||||
],
|
],
|
||||||
'STDEV' => [
|
'STDEV' => [
|
||||||
|
|
@ -2288,12 +2288,12 @@ class Calculation
|
||||||
],
|
],
|
||||||
'STDEVP' => [
|
'STDEVP' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'STDEVP'],
|
'functionCall' => [Statistical\StandardDeviations::class, 'STDEVP'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'STDEVPA' => [
|
'STDEVPA' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'STDEVPA'],
|
'functionCall' => [Statistical\StandardDeviations::class, 'STDEVPA'],
|
||||||
'argumentCount' => '1+',
|
'argumentCount' => '1+',
|
||||||
],
|
],
|
||||||
'STEYX' => [
|
'STEYX' => [
|
||||||
|
|
@ -2469,7 +2469,7 @@ class Calculation
|
||||||
],
|
],
|
||||||
'TRIMMEAN' => [
|
'TRIMMEAN' => [
|
||||||
'category' => Category::CATEGORY_STATISTICAL,
|
'category' => Category::CATEGORY_STATISTICAL,
|
||||||
'functionCall' => [Statistical::class, 'TRIMMEAN'],
|
'functionCall' => [Statistical\Averages\Mean::class, 'trim'],
|
||||||
'argumentCount' => '2',
|
'argumentCount' => '2',
|
||||||
],
|
],
|
||||||
'TRUE' => [
|
'TRUE' => [
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,14 @@ use PhpOffice\PhpSpreadsheet\Calculation\Statistical\StandardDeviations;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends;
|
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends;
|
||||||
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances;
|
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Variances;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated 1.18.0
|
||||||
|
*/
|
||||||
class Statistical
|
class Statistical
|
||||||
{
|
{
|
||||||
const LOG_GAMMA_X_MAX_VALUE = 2.55e305;
|
const LOG_GAMMA_X_MAX_VALUE = 2.55e305;
|
||||||
const EPS = 2.22e-16;
|
const EPS = 2.22e-16;
|
||||||
const MAX_VALUE = 1.2e308;
|
const MAX_VALUE = 1.2e308;
|
||||||
const MAX_ITERATIONS = 256;
|
|
||||||
const SQRT2PI = 2.5066282746310005024157652848110452530069867406099;
|
const SQRT2PI = 2.5066282746310005024157652848110452530069867406099;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -428,48 +430,18 @@ class Statistical
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* DEVSQ(value1[,value2[, ...]])
|
* DEVSQ(value1[,value2[, ...]])
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
* @see Statistical\Deviations::sumSquares()
|
||||||
|
* Use the sumSquares() method in the Statistical\Deviations class instead
|
||||||
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float|string
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function DEVSQ(...$args)
|
public static function DEVSQ(...$args)
|
||||||
{
|
{
|
||||||
$aArgs = Functions::flattenArrayIndexed($args);
|
return Statistical\Deviations::sumSquares(...$args);
|
||||||
|
|
||||||
// Return value
|
|
||||||
$returnValue = null;
|
|
||||||
|
|
||||||
$aMean = Averages::average($aArgs);
|
|
||||||
if ($aMean != Functions::DIV0()) {
|
|
||||||
$aCount = -1;
|
|
||||||
foreach ($aArgs as $k => $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if (
|
|
||||||
(is_bool($arg)) &&
|
|
||||||
((!Functions::isCellValue($k)) ||
|
|
||||||
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))
|
|
||||||
) {
|
|
||||||
$arg = (int) $arg;
|
|
||||||
}
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
if ($returnValue === null) {
|
|
||||||
$returnValue = ($arg - $aMean) ** 2;
|
|
||||||
} else {
|
|
||||||
$returnValue += ($arg - $aMean) ** 2;
|
|
||||||
}
|
|
||||||
++$aCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
if ($returnValue === null) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::NA();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -671,18 +643,18 @@ class Statistical
|
||||||
* Calculates the probability that a member of a standard normal population will fall between
|
* Calculates the probability that a member of a standard normal population will fall between
|
||||||
* the mean and z standard deviations from the mean.
|
* the mean and z standard deviations from the mean.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
* @see Statistical\Distributions\StandardNormal::gauss()
|
||||||
|
* Use the gauss() method in the Statistical\Distributions\StandardNormal class instead
|
||||||
|
*
|
||||||
* @param float $value
|
* @param float $value
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
public static function GAUSS($value)
|
public static function GAUSS($value)
|
||||||
{
|
{
|
||||||
$value = Functions::flattenSingleValue($value);
|
return Statistical\Distributions\StandardNormal::gauss($value);
|
||||||
if (!is_numeric($value)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Statistical\Distributions\Normal::distribution($value, 0, 1, true) - 0.5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -695,23 +667,18 @@ class Statistical
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* GEOMEAN(value1[,value2[, ...]])
|
* GEOMEAN(value1[,value2[, ...]])
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
* @see Statistical\Averages\Mean::geometric()
|
||||||
|
* Use the geometric() method in the Statistical\Averages\Mean class instead
|
||||||
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float|string
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function GEOMEAN(...$args)
|
public static function GEOMEAN(...$args)
|
||||||
{
|
{
|
||||||
$aArgs = Functions::flattenArray($args);
|
return Statistical\Averages\Mean::geometric(...$args);
|
||||||
|
|
||||||
$aMean = MathTrig\Product::evaluate($aArgs);
|
|
||||||
if (is_numeric($aMean) && ($aMean > 0)) {
|
|
||||||
$aCount = Counts::COUNT($aArgs);
|
|
||||||
if (Minimum::MIN($aArgs) > 0) {
|
|
||||||
return $aMean ** (1 / $aCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -745,38 +712,18 @@ class Statistical
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* HARMEAN(value1[,value2[, ...]])
|
* HARMEAN(value1[,value2[, ...]])
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
* @see Statistical\Averages\Mean::harmonic()
|
||||||
|
* Use the harmonic() method in the Statistical\Averages\Mean class instead
|
||||||
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float|string
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function HARMEAN(...$args)
|
public static function HARMEAN(...$args)
|
||||||
{
|
{
|
||||||
// Return value
|
return Statistical\Averages\Mean::harmonic(...$args);
|
||||||
$returnValue = 0;
|
|
||||||
|
|
||||||
// Loop through arguments
|
|
||||||
$aArgs = Functions::flattenArray($args);
|
|
||||||
if (Minimum::MIN($aArgs) < 0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
$aCount = 0;
|
|
||||||
foreach ($aArgs as $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
if ($arg <= 0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
$returnValue += (1 / $arg);
|
|
||||||
++$aCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
if ($aCount > 0) {
|
|
||||||
return 1 / ($returnValue / $aCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::NA();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -835,40 +782,18 @@ class Statistical
|
||||||
* kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a
|
* kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a
|
||||||
* relatively flat distribution.
|
* relatively flat distribution.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
* @see Statistical\Deviations::kurtosis()
|
||||||
|
* Use the kurtosis() method in the Statistical\Deviations class instead
|
||||||
|
*
|
||||||
* @param array ...$args Data Series
|
* @param array ...$args Data Series
|
||||||
*
|
*
|
||||||
* @return float|string
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function KURT(...$args)
|
public static function KURT(...$args)
|
||||||
{
|
{
|
||||||
$aArgs = Functions::flattenArrayIndexed($args);
|
return Statistical\Deviations::kurtosis(...$args);
|
||||||
$mean = Averages::average($aArgs);
|
|
||||||
$stdDev = StandardDeviations::STDEV($aArgs);
|
|
||||||
|
|
||||||
if ($stdDev > 0) {
|
|
||||||
$count = $summer = 0;
|
|
||||||
// Loop through arguments
|
|
||||||
foreach ($aArgs as $k => $arg) {
|
|
||||||
if (
|
|
||||||
(is_bool($arg)) &&
|
|
||||||
(!Functions::isMatrixValue($k))
|
|
||||||
) {
|
|
||||||
} else {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
$summer += (($arg - $mean) / $stdDev) ** 4;
|
|
||||||
++$count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return
|
|
||||||
if ($count > 3) {
|
|
||||||
return $summer * ($count * ($count + 1) / (($count - 1) * ($count - 2) * ($count - 3))) - (3 * ($count - 1) ** 2 / (($count - 2) * ($count - 3)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::DIV0();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -880,37 +805,18 @@ class Statistical
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* LARGE(value1[,value2[, ...]],entry)
|
* LARGE(value1[,value2[, ...]],entry)
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
* @see Statistical\Size::large()
|
||||||
|
* Use the large() method in the Statistical\Size class instead
|
||||||
|
*
|
||||||
* @param mixed $args Data values
|
* @param mixed $args Data values
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
public static function LARGE(...$args)
|
public static function LARGE(...$args)
|
||||||
{
|
{
|
||||||
$aArgs = Functions::flattenArray($args);
|
return Statistical\Size::large(...$args);
|
||||||
$entry = array_pop($aArgs);
|
|
||||||
|
|
||||||
if ((is_numeric($entry)) && (!is_string($entry))) {
|
|
||||||
$entry = (int) floor($entry);
|
|
||||||
|
|
||||||
// Calculate
|
|
||||||
$mArgs = [];
|
|
||||||
foreach ($aArgs as $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
$mArgs[] = $arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$count = Counts::COUNT($mArgs);
|
|
||||||
--$entry;
|
|
||||||
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
rsort($mArgs);
|
|
||||||
|
|
||||||
return $mArgs[$entry];
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1503,40 +1409,18 @@ class Statistical
|
||||||
* asymmetric tail extending toward more positive values. Negative skewness indicates a
|
* asymmetric tail extending toward more positive values. Negative skewness indicates a
|
||||||
* distribution with an asymmetric tail extending toward more negative values.
|
* distribution with an asymmetric tail extending toward more negative values.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
* @see Statistical\Deviations::skew()
|
||||||
|
* Use the skew() method in the Statistical\Deviations class instead
|
||||||
|
*
|
||||||
* @param array ...$args Data Series
|
* @param array ...$args Data Series
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
public static function SKEW(...$args)
|
public static function SKEW(...$args)
|
||||||
{
|
{
|
||||||
$aArgs = Functions::flattenArrayIndexed($args);
|
return Statistical\Deviations::skew(...$args);
|
||||||
$mean = Averages::average($aArgs);
|
|
||||||
$stdDev = StandardDeviations::STDEV($aArgs);
|
|
||||||
|
|
||||||
if ($stdDev === 0.0 || is_string($stdDev)) {
|
|
||||||
return Functions::DIV0();
|
|
||||||
}
|
|
||||||
|
|
||||||
$count = $summer = 0;
|
|
||||||
// Loop through arguments
|
|
||||||
foreach ($aArgs as $k => $arg) {
|
|
||||||
if ((is_bool($arg)) && (!Functions::isMatrixValue($k))) {
|
|
||||||
} elseif (!is_numeric($arg)) {
|
|
||||||
return Functions::VALUE();
|
|
||||||
} else {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
$summer += (($arg - $mean) / $stdDev) ** 3;
|
|
||||||
++$count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($count > 2) {
|
|
||||||
return $summer * ($count / (($count - 1) * ($count - 2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::DIV0();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1568,38 +1452,18 @@ class Statistical
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* SMALL(value1[,value2[, ...]],entry)
|
* SMALL(value1[,value2[, ...]],entry)
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
* @see Statistical\Size::small()
|
||||||
|
* Use the small() method in the Statistical\Size class instead
|
||||||
|
*
|
||||||
* @param mixed $args Data values
|
* @param mixed $args Data values
|
||||||
*
|
*
|
||||||
* @return float|string The result, or a string containing an error
|
* @return float|string The result, or a string containing an error
|
||||||
*/
|
*/
|
||||||
public static function SMALL(...$args)
|
public static function SMALL(...$args)
|
||||||
{
|
{
|
||||||
$aArgs = Functions::flattenArray($args);
|
return Statistical\Size::small(...$args);
|
||||||
|
|
||||||
// Calculate
|
|
||||||
$entry = array_pop($aArgs);
|
|
||||||
|
|
||||||
if ((is_numeric($entry)) && (!is_string($entry))) {
|
|
||||||
$entry = (int) floor($entry);
|
|
||||||
|
|
||||||
$mArgs = [];
|
|
||||||
foreach ($aArgs as $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
$mArgs[] = $arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$count = Counts::COUNT($mArgs);
|
|
||||||
--$entry;
|
|
||||||
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
sort($mArgs);
|
|
||||||
|
|
||||||
return $mArgs[$entry];
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1607,6 +1471,11 @@ class Statistical
|
||||||
*
|
*
|
||||||
* Returns a normalized value from a distribution characterized by mean and standard_dev.
|
* Returns a normalized value from a distribution characterized by mean and standard_dev.
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
* @see Statistical\Standardize::execute()
|
||||||
|
* Use the execute() method in the Statistical\Standardize class instead
|
||||||
|
*
|
||||||
* @param float $value Value to normalize
|
* @param float $value Value to normalize
|
||||||
* @param float $mean Mean Value
|
* @param float $mean Mean Value
|
||||||
* @param float $stdDev Standard Deviation
|
* @param float $stdDev Standard Deviation
|
||||||
|
|
@ -1615,19 +1484,7 @@ class Statistical
|
||||||
*/
|
*/
|
||||||
public static function STANDARDIZE($value, $mean, $stdDev)
|
public static function STANDARDIZE($value, $mean, $stdDev)
|
||||||
{
|
{
|
||||||
$value = Functions::flattenSingleValue($value);
|
return Statistical\Standardize::execute($value, $mean, $stdDev);
|
||||||
$mean = Functions::flattenSingleValue($mean);
|
|
||||||
$stdDev = Functions::flattenSingleValue($stdDev);
|
|
||||||
|
|
||||||
if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) {
|
|
||||||
if ($stdDev <= 0) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($value - $mean) / $stdDev;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1812,42 +1669,18 @@ class Statistical
|
||||||
* Excel Function:
|
* Excel Function:
|
||||||
* TRIMEAN(value1[,value2[, ...]], $discard)
|
* TRIMEAN(value1[,value2[, ...]], $discard)
|
||||||
*
|
*
|
||||||
|
* @Deprecated 1.18.0
|
||||||
|
*
|
||||||
|
*@see Statistical\Averages\Mean::trim()
|
||||||
|
* Use the trim() method in the Statistical\Averages\Mean class instead
|
||||||
|
*
|
||||||
* @param mixed $args Data values
|
* @param mixed $args Data values
|
||||||
*
|
*
|
||||||
* @return float|string
|
* @return float|string
|
||||||
*/
|
*/
|
||||||
public static function TRIMMEAN(...$args)
|
public static function TRIMMEAN(...$args)
|
||||||
{
|
{
|
||||||
$aArgs = Functions::flattenArray($args);
|
return Statistical\Averages\Mean::trim(...$args);
|
||||||
|
|
||||||
// Calculate
|
|
||||||
$percent = array_pop($aArgs);
|
|
||||||
|
|
||||||
if ((is_numeric($percent)) && (!is_string($percent))) {
|
|
||||||
if (($percent < 0) || ($percent > 1)) {
|
|
||||||
return Functions::NAN();
|
|
||||||
}
|
|
||||||
|
|
||||||
$mArgs = [];
|
|
||||||
foreach ($aArgs as $arg) {
|
|
||||||
// Is it a numeric value?
|
|
||||||
if ((is_numeric($arg)) && (!is_string($arg))) {
|
|
||||||
$mArgs[] = $arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$discard = floor(Counts::COUNT($mArgs) * $percent / 2);
|
|
||||||
sort($mArgs);
|
|
||||||
|
|
||||||
for ($i = 0; $i < $discard; ++$i) {
|
|
||||||
array_pop($mArgs);
|
|
||||||
array_shift($mArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Averages::average($mArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Functions::VALUE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1860,12 +1693,12 @@ class Statistical
|
||||||
*
|
*
|
||||||
* @Deprecated 1.17.0
|
* @Deprecated 1.17.0
|
||||||
*
|
*
|
||||||
|
*@see Statistical\Variances::VAR()
|
||||||
|
* Use the VAR() method in the Statistical\Variances class instead
|
||||||
|
*
|
||||||
* @param mixed ...$args Data values
|
* @param mixed ...$args Data values
|
||||||
*
|
*
|
||||||
* @return float|string (string if result is an error)
|
* @return float|string (string if result is an error)
|
||||||
*
|
|
||||||
*@see Statistical\Variances::VAR()
|
|
||||||
* Use the VAR() method in the Statistical\Variances class instead
|
|
||||||
*/
|
*/
|
||||||
public static function VARFunc(...$args)
|
public static function VARFunc(...$args)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Counts;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Minimum;
|
||||||
|
|
||||||
|
class Mean
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* GEOMEAN.
|
||||||
|
*
|
||||||
|
* Returns the geometric mean of an array or range of positive data. For example, you
|
||||||
|
* can use GEOMEAN to calculate average growth rate given compound interest with
|
||||||
|
* variable rates.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* GEOMEAN(value1[,value2[, ...]])
|
||||||
|
*
|
||||||
|
* @param mixed ...$args Data values
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function geometric(...$args)
|
||||||
|
{
|
||||||
|
$aArgs = Functions::flattenArray($args);
|
||||||
|
|
||||||
|
$aMean = MathTrig\Product::evaluate($aArgs);
|
||||||
|
if (is_numeric($aMean) && ($aMean > 0)) {
|
||||||
|
$aCount = Counts::COUNT($aArgs);
|
||||||
|
if (Minimum::MIN($aArgs) > 0) {
|
||||||
|
return $aMean ** (1 / $aCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HARMEAN.
|
||||||
|
*
|
||||||
|
* Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the
|
||||||
|
* arithmetic mean of reciprocals.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* HARMEAN(value1[,value2[, ...]])
|
||||||
|
*
|
||||||
|
* @param mixed ...$args Data values
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function harmonic(...$args)
|
||||||
|
{
|
||||||
|
// Loop through arguments
|
||||||
|
$aArgs = Functions::flattenArray($args);
|
||||||
|
if (Minimum::MIN($aArgs) < 0) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
|
||||||
|
$returnValue = 0;
|
||||||
|
$aCount = 0;
|
||||||
|
foreach ($aArgs as $arg) {
|
||||||
|
// Is it a numeric value?
|
||||||
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
|
if ($arg <= 0) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
$returnValue += (1 / $arg);
|
||||||
|
++$aCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
if ($aCount > 0) {
|
||||||
|
return 1 / ($returnValue / $aCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::NA();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TRIMMEAN.
|
||||||
|
*
|
||||||
|
* Returns the mean of the interior of a data set. TRIMMEAN calculates the mean
|
||||||
|
* taken by excluding a percentage of data points from the top and bottom tails
|
||||||
|
* of a data set.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* TRIMEAN(value1[,value2[, ...]], $discard)
|
||||||
|
*
|
||||||
|
* @param mixed $args Data values
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function trim(...$args)
|
||||||
|
{
|
||||||
|
$aArgs = Functions::flattenArray($args);
|
||||||
|
|
||||||
|
// Calculate
|
||||||
|
$percent = array_pop($aArgs);
|
||||||
|
|
||||||
|
if ((is_numeric($percent)) && (!is_string($percent))) {
|
||||||
|
if (($percent < 0) || ($percent > 1)) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
|
||||||
|
$mArgs = [];
|
||||||
|
foreach ($aArgs as $arg) {
|
||||||
|
// Is it a numeric value?
|
||||||
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
|
$mArgs[] = $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$discard = floor(Counts::COUNT($mArgs) * $percent / 2);
|
||||||
|
sort($mArgs);
|
||||||
|
|
||||||
|
for ($i = 0; $i < $discard; ++$i) {
|
||||||
|
array_pop($mArgs);
|
||||||
|
array_shift($mArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Averages::average($mArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Deviations
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* DEVSQ.
|
||||||
|
*
|
||||||
|
* Returns the sum of squares of deviations of data points from their sample mean.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* DEVSQ(value1[,value2[, ...]])
|
||||||
|
*
|
||||||
|
* @param mixed ...$args Data values
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function sumSquares(...$args)
|
||||||
|
{
|
||||||
|
$aArgs = Functions::flattenArrayIndexed($args);
|
||||||
|
|
||||||
|
$aMean = Averages::average($aArgs);
|
||||||
|
if (!is_numeric($aMean)) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return value
|
||||||
|
$returnValue = 0.0;
|
||||||
|
$aCount = -1;
|
||||||
|
foreach ($aArgs as $k => $arg) {
|
||||||
|
// Is it a numeric value?
|
||||||
|
if (
|
||||||
|
(is_bool($arg)) &&
|
||||||
|
((!Functions::isCellValue($k)) ||
|
||||||
|
(Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE))
|
||||||
|
) {
|
||||||
|
$arg = (int) $arg;
|
||||||
|
}
|
||||||
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
|
$returnValue += ($arg - $aMean) ** 2;
|
||||||
|
++$aCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aCount === 0 ? Functions::VALUE() : $returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KURT.
|
||||||
|
*
|
||||||
|
* Returns the kurtosis of a data set. Kurtosis characterizes the relative peakedness
|
||||||
|
* or flatness of a distribution compared with the normal distribution. Positive
|
||||||
|
* kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a
|
||||||
|
* relatively flat distribution.
|
||||||
|
*
|
||||||
|
* @param array ...$args Data Series
|
||||||
|
*
|
||||||
|
* @return float|string
|
||||||
|
*/
|
||||||
|
public static function kurtosis(...$args)
|
||||||
|
{
|
||||||
|
$aArgs = Functions::flattenArrayIndexed($args);
|
||||||
|
$mean = Averages::average($aArgs);
|
||||||
|
if (!is_numeric($mean)) {
|
||||||
|
return Functions::DIV0();
|
||||||
|
}
|
||||||
|
$stdDev = StandardDeviations::STDEV($aArgs);
|
||||||
|
|
||||||
|
if ($stdDev > 0) {
|
||||||
|
$count = $summer = 0;
|
||||||
|
|
||||||
|
foreach ($aArgs as $k => $arg) {
|
||||||
|
if ((is_bool($arg)) && (!Functions::isMatrixValue($k))) {
|
||||||
|
} else {
|
||||||
|
// Is it a numeric value?
|
||||||
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
|
$summer += (($arg - $mean) / $stdDev) ** 4;
|
||||||
|
++$count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($count > 3) {
|
||||||
|
return $summer * ($count * ($count + 1) /
|
||||||
|
(($count - 1) * ($count - 2) * ($count - 3))) - (3 * ($count - 1) ** 2 /
|
||||||
|
(($count - 2) * ($count - 3)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::DIV0();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SKEW.
|
||||||
|
*
|
||||||
|
* Returns the skewness of a distribution. Skewness characterizes the degree of asymmetry
|
||||||
|
* of a distribution around its mean. Positive skewness indicates a distribution with an
|
||||||
|
* asymmetric tail extending toward more positive values. Negative skewness indicates a
|
||||||
|
* distribution with an asymmetric tail extending toward more negative values.
|
||||||
|
*
|
||||||
|
* @param array ...$args Data Series
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function skew(...$args)
|
||||||
|
{
|
||||||
|
$aArgs = Functions::flattenArrayIndexed($args);
|
||||||
|
$mean = Averages::average($aArgs);
|
||||||
|
if (!is_numeric($mean)) {
|
||||||
|
return Functions::DIV0();
|
||||||
|
}
|
||||||
|
$stdDev = StandardDeviations::STDEV($aArgs);
|
||||||
|
if ($stdDev === 0.0 || is_string($stdDev)) {
|
||||||
|
return Functions::DIV0();
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = $summer = 0;
|
||||||
|
// Loop through arguments
|
||||||
|
foreach ($aArgs as $k => $arg) {
|
||||||
|
if ((is_bool($arg)) && (!Functions::isMatrixValue($k))) {
|
||||||
|
} elseif (!is_numeric($arg)) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
} else {
|
||||||
|
// Is it a numeric value?
|
||||||
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
|
$summer += (($arg - $mean) / $stdDev) ** 3;
|
||||||
|
++$count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($count > 2) {
|
||||||
|
return $summer * ($count / (($count - 1) * ($count - 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::DIV0();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -55,6 +55,26 @@ class StandardNormal
|
||||||
return Normal::inverse($value, 0, 1);
|
return Normal::inverse($value, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GAUSS.
|
||||||
|
*
|
||||||
|
* Calculates the probability that a member of a standard normal population will fall between
|
||||||
|
* the mean and z standard deviations from the mean.
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function gauss($value)
|
||||||
|
{
|
||||||
|
$value = Functions::flattenSingleValue($value);
|
||||||
|
if (!is_numeric($value)) {
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::distribution($value, true) - 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZTEST.
|
* ZTEST.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Size
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* LARGE.
|
||||||
|
*
|
||||||
|
* Returns the nth largest value in a data set. You can use this function to
|
||||||
|
* select a value based on its relative standing.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* LARGE(value1[,value2[, ...]],entry)
|
||||||
|
*
|
||||||
|
* @param mixed $args Data values
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function large(...$args)
|
||||||
|
{
|
||||||
|
$aArgs = Functions::flattenArray($args);
|
||||||
|
$entry = array_pop($aArgs);
|
||||||
|
|
||||||
|
if ((is_numeric($entry)) && (!is_string($entry))) {
|
||||||
|
$entry = (int) floor($entry);
|
||||||
|
|
||||||
|
$mArgs = self::filter($aArgs);
|
||||||
|
$count = Counts::COUNT($mArgs);
|
||||||
|
--$entry;
|
||||||
|
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
rsort($mArgs);
|
||||||
|
|
||||||
|
return $mArgs[$entry];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMALL.
|
||||||
|
*
|
||||||
|
* Returns the nth smallest value in a data set. You can use this function to
|
||||||
|
* select a value based on its relative standing.
|
||||||
|
*
|
||||||
|
* Excel Function:
|
||||||
|
* SMALL(value1[,value2[, ...]],entry)
|
||||||
|
*
|
||||||
|
* @param mixed $args Data values
|
||||||
|
*
|
||||||
|
* @return float|string The result, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function small(...$args)
|
||||||
|
{
|
||||||
|
$aArgs = Functions::flattenArray($args);
|
||||||
|
|
||||||
|
$entry = array_pop($aArgs);
|
||||||
|
|
||||||
|
if ((is_numeric($entry)) && (!is_string($entry))) {
|
||||||
|
$entry = (int) floor($entry);
|
||||||
|
|
||||||
|
$mArgs = self::filter($aArgs);
|
||||||
|
$count = Counts::COUNT($mArgs);
|
||||||
|
--$entry;
|
||||||
|
if (($entry < 0) || ($entry >= $count) || ($count == 0)) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
sort($mArgs);
|
||||||
|
|
||||||
|
return $mArgs[$entry];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Functions::VALUE();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed[] $args Data values
|
||||||
|
*/
|
||||||
|
protected static function filter(array $args): array
|
||||||
|
{
|
||||||
|
$mArgs = [];
|
||||||
|
|
||||||
|
foreach ($args as $arg) {
|
||||||
|
// Is it a numeric value?
|
||||||
|
if ((is_numeric($arg)) && (!is_string($arg))) {
|
||||||
|
$mArgs[] = $arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $mArgs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
|
||||||
|
class Standardize extends StatisticalValidations
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* STANDARDIZE.
|
||||||
|
*
|
||||||
|
* Returns a normalized value from a distribution characterized by mean and standard_dev.
|
||||||
|
*
|
||||||
|
* @param float $value Value to normalize
|
||||||
|
* @param float $mean Mean Value
|
||||||
|
* @param float $stdDev Standard Deviation
|
||||||
|
*
|
||||||
|
* @return float|string Standardized value, or a string containing an error
|
||||||
|
*/
|
||||||
|
public static function execute($value, $mean, $stdDev)
|
||||||
|
{
|
||||||
|
$value = Functions::flattenSingleValue($value);
|
||||||
|
$mean = Functions::flattenSingleValue($mean);
|
||||||
|
$stdDev = Functions::flattenSingleValue($stdDev);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$value = self::validateFloat($value);
|
||||||
|
$mean = self::validateFloat($mean);
|
||||||
|
$stdDev = self::validateFloat($stdDev);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($stdDev <= 0) {
|
||||||
|
return Functions::NAN();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($value - $mean) / $stdDev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\Statistical;
|
||||||
|
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Calculation\Statistical;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class DevSqTest extends TestCase
|
||||||
|
{
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
Functions::setCompatibilityMode(Functions::COMPATIBILITY_EXCEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerDEVSQ
|
||||||
|
*
|
||||||
|
* @param mixed $expectedResult
|
||||||
|
*/
|
||||||
|
public function testDEVSQ($expectedResult, ...$args): void
|
||||||
|
{
|
||||||
|
$result = Statistical::DEVSQ(...$args);
|
||||||
|
self::assertEqualsWithDelta($expectedResult, $result, 1E-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function providerDEVSQ(): array
|
||||||
|
{
|
||||||
|
return require 'tests/data/Calculation/Statistical/DEVSQ.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
48,
|
||||||
|
[4, 5, 8, 7, 11, 4, 3],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
47.5,
|
||||||
|
[1, 3, 5, 2, 9, 7],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
79.875,
|
||||||
|
[1, 3, 5, 2, 9, 7, 8, 10],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#NUM!',
|
||||||
|
['A', 'B', 'C', 'D'],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
@ -13,6 +13,10 @@ return [
|
||||||
'#NUM!',
|
'#NUM!',
|
||||||
2.5, -3, 0.5, 1, 3,
|
2.5, -3, 0.5, 1, 3,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'#NUM!',
|
||||||
|
2.5, 3, 0.0, 1, 3,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'#N/A',
|
'#N/A',
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,12 @@ return[
|
||||||
0.532657874050135,
|
0.532657874050135,
|
||||||
[4, 5, 4, 4, 4, 4, 4, 2, 3, 5, 5, 3],
|
[4, 5, 4, 4, 4, 4, 4, 2, 3, 5, 5, 3],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'#DIV/0!',
|
||||||
|
['A', 'B', 'C', 'D', 'E'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#DIV/0!',
|
||||||
|
[1, 2, 3, 'A', 'B', 'C', 'D', 'E'],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,12 @@ return [
|
||||||
'#DIV/0!',
|
'#DIV/0!',
|
||||||
[1, 1],
|
[1, 1],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'#DIV/0!',
|
||||||
|
[1, 1],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'#DIV/0!',
|
||||||
|
['A', 'B', 'C', 'D', 'E'],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,6 @@ return [
|
||||||
[-0.676, 63.81, 65.5, 2.5],
|
[-0.676, 63.81, 65.5, 2.5],
|
||||||
['#NUM!', 1.1, -2.2, -3.3],
|
['#NUM!', 1.1, -2.2, -3.3],
|
||||||
['#VALUE!', 'NAN', 0.1, 0.2],
|
['#VALUE!', 'NAN', 0.1, 0.2],
|
||||||
|
['#VALUE!', 0.1, 'NAN', 0.2],
|
||||||
|
['#VALUE!', 0.1, 0.2, 'NAN'],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue