Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

welcome PHP 8.4 #70

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest, windows-latest]
php: [8.1, 8.2, 8.3]
php: [8.1, 8.2, 8.3, 8.4]
exclude:
- os: windows-latest
php: [8.1, 8.3]
php: [8.1, 8.2, 8.4]

name: P${{ matrix.php }} - ${{ matrix.os }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/static-code-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest]
php: [8.1]
php: [8.3]
stability: [prefer-stable]

name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }}
Expand Down
1 change: 1 addition & 0 deletions .phpunit.cache/test-results
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":"pest_2.36.0","defects":[],"times":{"P\\Tests\\StatisticTest::__pest_evaluable_it_calculates_variance":0,"P\\Tests\\StatisticTest::__pest_evaluable_it_can_calculate_statistics_again":0.001,"P\\Tests\\StatisticTest::__pest_evaluable_it_can_distinct_numeric_array":0,"P\\Tests\\StatisticTest::__pest_evaluable_it_can_calculate_mean":0.001,"P\\Tests\\StatisticTest::__pest_evaluable_it_can_valuesToString":0,"P\\Tests\\StatisticTest::__pest_evaluable_it_calculates_geometric_mean":0.001,"P\\Tests\\StatisticTest::__pest_evaluable_it_can_calculate_statistics_again_and_again":0.001,"P\\Tests\\StatisticTest::__pest_evaluable_it_can_calculate_statistics":0.001,"P\\Tests\\StatisticTest::__pest_evaluable_it_calculates_pvariance":0,"P\\Tests\\StatisticTest::__pest_evaluable_it_can_calculate_mean_again":0,"P\\Tests\\StatisticTest::__pest_evaluable_it_calculates_Population_standard_deviation":0.001,"P\\Tests\\StatisticTest::__pest_evaluable_it_calculates_Sample_standard_deviation":0.001,"P\\Tests\\StatisticTest::__pest_evaluable_it_can_strip_zeros":0,"P\\Tests\\StatisticTest::__pest_evaluable_it_calculates_harmonic_mean":0,"P\\Tests\\ArchTest::__pest_evaluable_constructor":0,"P\\Tests\\ArchTest::__pest_evaluable_to_be_final":0.052,"P\\Tests\\ArchTest::__pest_evaluable_ensures_no_debugging":0.102,"P\\Tests\\ArchTest::__pest_evaluable_make":0.012,"P\\Tests\\FrequenciesTest::__pest_evaluable_it_can_calculate_cumulative_relative_frequencies":0,"P\\Tests\\FrequenciesTest::__pest_evaluable_it_can_calculate_thirdQuartile":0,"P\\Tests\\FrequenciesTest::__pest_evaluable_it_can_calculate_frequencies":0,"P\\Tests\\FrequenciesTest::__pest_evaluable_it_can_calculate_cumulative_frequencies":0,"P\\Tests\\FrequenciesTest::__pest_evaluable_it_can_calculate_relative_frequencies":0,"P\\Tests\\FrequenciesTest::__pest_evaluable_it_can_calculate_firstQuartile":0,"P\\Tests\\MathTest::__pest_evaluable_it_is_odd__static_":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation_with_external_dataset#('median', [1, 3, 5], 3)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation_with_external_dataset#('mean', [-1.0, 2.5, 3.25, \u2026], 2.625)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation_with_external_dataset#('medianLow', [1, 3, 5, \u2026], 3)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation_with_external_dataset#('median', [1, 3, 5, \u2026], 4)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation_with_external_dataset#('mean', [1, 2, 3, \u2026], 2.8)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation_with_external_dataset#('medianLow', [1, 3, 5], 3)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Mean":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Mean_dataset#([1, 2, 3, \u2026], 2.8)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Mean_dataset#([-1.0, 2.5, 3.25, \u2026], 2.625)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation#('medianLow', [1, 3, 5, \u2026], 3)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation#('medianLow', [1, 3, 5], 3)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation#('mean', [-1.0, 2.5, 3.25, \u2026], 2.625)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation#('median', [1, 3, 5], 3)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation#('median', [1, 3, 5, \u2026], 4)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Dynamic_operation#('mean', [1, 2, 3, \u2026], 2.8)":0,"P\\Tests\\StatDatasetTest::__pest_evaluable__Calculating_Stat_operation__\u2192_it_Mean_chain_expect":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_mode__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_Population_standard_deviation__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_linear_regression__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_correlation__wrong_usage__static_":0.001,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_linear_regression_with_not_valid_input__static_":0.001,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_Sample_standard_deviation__static_":0.001,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_first_quartiles__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_geometric_mean__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_multimode__static_":0.001,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_quantiles__static_":0.001,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_pvariance__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_covariance__wrong_usage__static_":0.001,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_median_high__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_median_low__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_covariance__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_mean__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_correlation__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_median__static_":0.001,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_variance__static_":0,"P\\Tests\\StatTest::__pest_evaluable_it_calculates_harmonic_mean__static_":0,"P\\Tests\\FreqTest::__pest_evaluable_it_can_calculate_grouped_frequency_table_by_size__static_":0.001,"P\\Tests\\FreqTest::__pest_evaluable_it_can_calculate_freq_table__static_":0.005,"P\\Tests\\FreqTest::__pest_evaluable_it_can_calculate_relativefreq_table__static_":0.001,"P\\Tests\\FreqTest::__pest_evaluable_it_can_calculate_grouped_frequency_table__static_":0.003,"P\\Tests\\StatFromCsvTest::__pest_evaluable_it_parse_CSV":0.043}}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 1.0.1 - 2024-11-21

- Welcome PHP 8.4

## 1.0.0 - 2023-12-26

- Fixed `median()` function to handle unsorted data by @keatis
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
}
],
"require": {
"php": "^8.1"
"php": "^8.1|^8.2|^8.3|^8.4"
},
"require-dev": {
"laravel/pint": "^1.13",
Expand Down
2 changes: 1 addition & 1 deletion examples/frequencies.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*/

$s = Statistics::make(
[98, 90, 70, 18, 92, 92, 55, 83, 45, 95, 88, 76]
[98, 90, 70, 18, 92, 92, 55, 83, 45, 95, 88, 76],
);
$a = $s->frequencies();
print_r($a);
Expand Down
4 changes: 2 additions & 2 deletions examples/stat.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
use HiFolks\Statistics\Stat;

$freq = Freq::frequencies(
['red', 'blue', 'blue', 'red', 'green', 'red', 'red']
['red', 'blue', 'blue', 'red', 'green', 'red', 'red'],
);
var_dump($freq);
$mode = Stat::mode(
['red', 'blue', 'blue', 'red', 'green', 'red', 'red']
['red', 'blue', 'blue', 'red', 'green', 'red', 'red'],
);

var_dump($mode);
2 changes: 1 addition & 1 deletion examples/stat_methods.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
// 1.3720238095238095
[$slope, $intercept] = Stat::linearRegression(
[1971, 1975, 1979, 1982, 1983],
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5],
);
// 0.31
// -610.18
Expand Down
28 changes: 16 additions & 12 deletions src/Stat.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public static function mean(array $data): int|float|null
if (self::count($data) === 0) {
throw new InvalidDataInputException('The data must not be empty.');
}
// @phpstan-ignore-next-line
if (!empty(array_filter($data, 'is_string'))) {
throw new InvalidDataInputException('The data array contains a string.');
}
$sum = array_sum($data);

return $sum / self::count($data);
Expand Down Expand Up @@ -70,7 +74,7 @@ public static function median(array $data, string $medianType = self::MEDIAN_TYP
return match ($medianType) {
self::MEDIAN_TYPE_LOW => ($data[$index - 1]),
self::MEDIAN_TYPE_HIGH => $data[$index],
default => ($data[$index - 1] + $data[$index]) / 2
default => ($data[$index - 1] + $data[$index]) / 2,
};
}

Expand Down Expand Up @@ -174,7 +178,7 @@ public static function quantiles(array $data, int $n = 4, ?int $round = null): a
$count = self::count($data);
if ($count < 2 || $n < 1) {
throw new InvalidDataInputException(
'The size of the data must be greater than 2 and the number of quantiles must be greater than 1.'
'The size of the data must be greater than 2 and the number of quantiles must be greater than 1.',
);
}

Expand Down Expand Up @@ -393,12 +397,12 @@ public static function covariance(array $x, array $y): false|float
$countY = count($y);
if ($countX !== $countY) {
throw new InvalidDataInputException(
'Covariance requires that both inputs have same number of data points.'
'Covariance requires that both inputs have same number of data points.',
);
}
if ($countX < 2) {
throw new InvalidDataInputException(
'Covariance requires at least two data points.'
'Covariance requires at least two data points.',
);
}
$meanX = self::mean($x);
Expand All @@ -409,13 +413,13 @@ public static function covariance(array $x, array $y): false|float
$valueX = $x[$pos];
if (!is_numeric($valueX)) {
throw new InvalidDataInputException(
'Covariance requires numeric data points.'
'Covariance requires numeric data points.',
);
}
$valueY = $y[$pos];
if (!is_numeric($valueY)) {
throw new InvalidDataInputException(
'Covariance requires numeric data points.'
'Covariance requires numeric data points.',
);
}
$diffX = $valueX - $meanX;
Expand Down Expand Up @@ -448,12 +452,12 @@ public static function correlation(array $x, array $y): false|float
$countY = count($y);
if ($countX !== $countY) {
throw new InvalidDataInputException(
'Correlation requires that both inputs have same number of data points.'
'Correlation requires that both inputs have same number of data points.',
);
}
if ($countX < 2) {
throw new InvalidDataInputException(
'Correlation requires at least two data points.'
'Correlation requires at least two data points.',
);
}
$meanX = self::mean($x);
Expand All @@ -472,7 +476,7 @@ public static function correlation(array $x, array $y): false|float
$b = sqrt($bx * $by);
if ($b == 0) {
throw new InvalidDataInputException(
'Correlation, at least one of the inputs is constant.'
'Correlation, at least one of the inputs is constant.',
);
}

Expand All @@ -494,12 +498,12 @@ public static function linearRegression(array $x, array $y): array
$countY = count($y);
if ($countX !== $countY) {
throw new InvalidDataInputException(
'Linear regression requires that both inputs have same number of data points.'
'Linear regression requires that both inputs have same number of data points.',
);
}
if ($countX < 2) {
throw new InvalidDataInputException(
'Linear regression requires at least two data points.'
'Linear regression requires at least two data points.',
);
}
$sumX = array_sum($x);
Expand All @@ -514,7 +518,7 @@ public static function linearRegression(array $x, array $y): array
$denominator = (($countX * $sumXX) - ($sumX * $sumX));
if ($denominator === 0) {
throw new InvalidDataInputException(
'Linear regression, the inputs is constant.'
'Linear regression, the inputs is constant.',
);
}
$slope = (($countX * $sumXY) - ($sumX * $sumY)) / $denominator;
Expand Down
2 changes: 1 addition & 1 deletion src/Statistics.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Statistics
* @param array<mixed> $values
*/
public function __construct(
array $values = []
array $values = [],
) {
$this->values = array_values($values);
$this->originalArray = $values;
Expand Down
82 changes: 41 additions & 41 deletions tests/FreqTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,69 +4,69 @@

it('can calculate freq table (static)', function () {
expect(
Freq::frequencies([1, 2, 3, 4, 4])
Freq::frequencies([1, 2, 3, 4, 4]),
)->toMatchArray([4 => 2, 3 => 1, 1 => 1, 2 => 1]);
expect(
Freq::frequencies([])
Freq::frequencies([]),
)->toMatchArray([]);
$result = Freq::frequencies(['red', 'blue', 'blue', 'red', 'green', 'red', 'red']);
expect(
$result
$result,
)->toMatchArray(['red' => 4, 'blue' => 2, 'green' => 1]);
expect(
$result
$result,
)->toHaveCount(3);

expect(
$result['red']
$result['red'],
)->toEqual(4);
expect(
$result['blue']
$result['blue'],
)->toEqual(2);
expect(
$result['green']
$result['green'],
)->toEqual(1);

$result = Freq::frequencies([2.1, 2.7, 1.4, 2.45], true);
expect(
$result
$result,
)->toMatchArray([2 => 3, 1 => 1]);
expect(
$result
$result,
)->toHaveCount(2);
});

it('can calculate relativefreq table (static)', function () {
expect(
Freq::relativeFrequencies([1, 2, 3, 4, 4])
Freq::relativeFrequencies([1, 2, 3, 4, 4]),
)->toMatchArray([4 => 40, 3 => 20, 1 => 20, 2 => 20]);
expect(
Freq::relativeFrequencies([])
Freq::relativeFrequencies([]),
)->toMatchArray([]);
$result = Freq::relativeFrequencies(['red', 'blue', 'blue', 'red', 'green', 'red', 'red'], 2);
expect(
$result
$result,
)->toMatchArray(['red' => 57.14, 'blue' => 28.57, 'green' => 14.29]);
expect(
$result
$result,
)->toHaveCount(3);

expect(
$result['red']
$result['red'],
)->toEqual(57.14);
expect(
$result['blue']
$result['blue'],
)->toEqual(28.57);
expect(
$result['green']
$result['green'],
)->toEqual(14.29);

$result = Freq::relativeFrequencies([2.1, 2.7, 1.4, 2.45], true);
expect(
$result
$result,
)->toMatchArray([2 => 75, 1 => 25]);
expect(
$result
$result,
)->toHaveCount(2);
});

Expand All @@ -75,54 +75,54 @@
13, 14, 14, 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, ];
$table = Freq::frequencyTable($data, 7);
expect(
$table
$table,
)->toHaveCount(6);
expect(
$table
$table,
)->toMatchArray([1 => 3, 4 => 6, 7 => 10, 10 => 5, 13 => 5, 16 => 9]);
expect(
array_sum($table)
array_sum($table),
)->toEqual(count($data));

$table = Freq::frequencyTable($data, 6);
expect(
$table
$table,
)->toHaveCount(6);
expect(
$table
$table,
)->toMatchArray([1 => 3, 4 => 6, 7 => 10, 10 => 5, 13 => 5, 16 => 9]);
expect(
array_sum($table)
array_sum($table),
)->toEqual(count($data));

$table = Freq::frequencyTable($data, 8);
expect(
$table
$table,
)->toHaveCount(6);
expect(
$table
$table,
)->toMatchArray([1 => 3, 4 => 6, 7 => 10, 10 => 5, 13 => 5, 16 => 9]);
expect(
array_sum($table)
array_sum($table),
)->toEqual(count($data));

$table = Freq::frequencyTable($data, 3);
expect(
$table
$table,
)->toHaveCount(3);
expect(
$table
$table,
)->toMatchArray([1 => 9, 7 => 15, 13 => 14]);
expect(
array_sum($table)
array_sum($table),
)->toEqual(count($data));

$table = Freq::frequencyTable($data);
expect(
$table
$table,
)->toHaveCount(18);
expect(
$table
$table,
)->toMatchArray([1 => 3, 2 => 0, 3 => 0, 4 => 2, 5 => 3, 6 => 1, 7 => 1, 8 => 3, 9 => 6,
10 => 2, 11 => 1, 12 => 2, 13 => 1, 14 => 2, 15 => 2, 16 => 4, 17 => 3, 18 => 2, ]);
});
Expand All @@ -132,34 +132,34 @@
13, 14, 14, 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, ];
$table = Freq::frequencyTableBySize($data, 4);
expect(
$table
$table,
)->toHaveCount(5);
expect(
$table
$table,
)->toMatchArray([1 => 5, 5 => 8, 9 => 11, 13 => 9, 17 => 5]);
expect(
array_sum($table)
array_sum($table),
)->toEqual(count($data));

$table = Freq::frequencyTableBySize($data, 5);
expect(
$table
$table,
)->toHaveCount(4);
expect(
$table
$table,
)->toMatchArray([1 => 8, 6 => 13, 11 => 8, 16 => 9]);
expect(
array_sum($table)
array_sum($table),
)->toEqual(count($data));

$table = Freq::frequencyTableBySize($data, 8);
expect(
$table
$table,
)->toHaveCount(3);
expect(
$table
$table,
)->toMatchArray([1 => 13, 9 => 20, 17 => 5]);
expect(
array_sum($table)
array_sum($table),
)->toEqual(count($data));
});
Loading