{"id":668,"date":"2025-05-12T21:06:41","date_gmt":"2025-05-12T19:06:41","guid":{"rendered":"https:\/\/renor.it\/a-descriptive-statistics-class-in-php\/"},"modified":"2025-12-20T15:53:57","modified_gmt":"2025-12-20T14:53:57","slug":"a-descriptive-statistics-class-in-php","status":"publish","type":"post","link":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/","title":{"rendered":"A Descriptive Statistics Class in PHP"},"content":{"rendered":"\n<p>In the world of software development, data analysis is becoming increasingly central. With the advent of artificial intelligence in the consumer market, many now use it to analyze statistical data as well. However, in many cases, the use of this technology is not required and is actually less efficient than a solid algorithm designed to take input data and return output data in a \u201cblack-box\u201d manner.  <\/p>\n\n<p>Artificial intelligence is now seen by many entrepreneurs as a trend, but it should only be used where it truly adds value. Speaking of efficiency, using AI to calculate a mean, a median, or a mode is not only like using a bazooka to kill a couple of flies, but it can also turn out to be slower, considering the inference times, compared to a finite state algorithm.  <\/p>\n\n<p>Even in contexts that are not strictly scientific or academic, knowing the fundamentals of descriptive statistics can prove extremely useful: from generating automated reports, to monitoring an application\u2019s performance, and even to building dashboards or analytical tools. <\/p>\n\n<p>In this article, we will build a PHP class that calculates the main descriptive statistical indicators\u2014such as mean, median, mode, variance, standard deviation, quartiles, and more\u2014from scratch, without relying on external libraries. The code will be clean, reusable, and ready to be transformed into a Composer package, which will be the subject of a follow-up article. <\/p>\n\n<h2 class=\"wp-block-heading\">Designing a simple yet extensible class<\/h2>\n\n<p>To build a useful and easily integrable descriptive statistics class, we will adopt an object-oriented structure aligned with SOLID principles, avoiding external dependencies and ensuring the possibility of future extension (e.g., support for associative datasets or reading from CSV files). <\/p>\n\n<p>The class will be designed to operate on arrays of numerical values and efficiently compute the main statistical indicators. The goal is to provide a simple interface.  <\/p>\n\n<p>First, let\u2019s create a new repository on GitHub, which you can find at the following link:<br\/><a href=\"https:\/\/github.com\/thesimon82\/descriptive-statistics-php\">https:\/\/github.com\/thesimon82\/descriptive-statistics-php<\/a><\/p>\n\n<p>Let\u2019s start implementing the methods.<\/p>\n\n<p>The project structure should be as follows: <\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"descriptive-statistics-php\/ \u251c\u2500 composer.json \u251c\u2500 composer.lock \u251c\u2500 phpunit.xml \u251c\u2500 examples\/ \u2502 \u2514\u2500 geometric_mean_demo.php \u2502 \u2514\u2500 harmonic_mean_demo.php \u2502 \u2514\u2500 iqr_demo.php \u2502 \u2514\u2500 mad_demo.php \u2502 \u2514\u2500 mean_demo.php \u2502 \u2514\u2500 median_demo.php \u2502 \u2514\u2500 min_max_demo.php \u2502 \u2514\u2500 mode_demo.php \u2502 \u2514\u2500 percentile_demo.php \u2502 \u2514\u2500 range_demo.php \u2502 \u2514\u2500 standard_deviation_demo.php \u2502 \u2514\u2500 trimmed_mean_demo.php \u2502 \u2514\u2500 variance_demo.php \u251c\u2500 src\/ \u2502 \u2514\u2500 DescriptiveStats.php \u251c\u2500 tests\/ \u2502 \u2514\u2500 DescriptiveStatsTest.php \u2514\u2500 vendor\/ \u2514\u2500 autoload.php\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">descriptive-statistics-php\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u251c\u2500 composer<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">json<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u251c\u2500 composer<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">lock<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u251c\u2500 phpunit<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">xml<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u251c\u2500 examples\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 geometric_mean_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 harmonic_mean_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 iqr_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 mad_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 mean_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 median_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 min_max_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 mode_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 percentile_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 range_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 standard_deviation_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 trimmed_mean_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 variance_demo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u251c\u2500 src\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 DescriptiveStats<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u251c\u2500 tests\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2502  \u2514\u2500 DescriptiveStatsTest<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">\u2514\u2500 vendor\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    \u2514\u2500 autoload<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #D4D4D4\">php<\/span><\/span><\/code><\/pre><\/div>\n\n<p>As you can see, I have also included a folder for adding tests on the class methods (optional) using PHPUnit. The phpunit.xml file defines the test folder and the PHPUnit sources, which must be installed via Composer from the Packagist repository <code>phpunit\/phpunit<\/code>, adding it as a development dependency using the command <code>composer require --dev phpunit\/phpunit ^10<\/code>. <\/p>\n\n<h2 class=\"wp-block-heading\">Mean<\/h2>\n\n<p>The <strong>arithmetic mean<\/strong> (or average) of a set of <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> numerical observations <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-5e8319f54f72e7dac2238515c1499b27_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;&#95;&#49;&#44;&#32;&#120;&#95;&#50;&#44;&#32;&#92;&#100;&#111;&#116;&#115;&#44;&#32;&#120;&#95;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"101\" style=\"vertical-align: -4px;\"\/> is obtained by summing all the values and dividing the result by the total number of observations. Formally, it is written as: <\/p>\n\n<p><br\/><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-6e56531130e72a8ea51283096d7d0308_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#98;&#97;&#114;&#123;&#120;&#125;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#110;&#125;&#32;&#92;&#115;&#117;&#109;&#95;&#123;&#105;&#61;&#49;&#125;&#94;&#123;&#110;&#125;&#32;&#120;&#95;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"22\" width=\"119\" style=\"vertical-align: -6px;\"\/><\/p>\n\n<p><br\/>where <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-20ebc7ea21d727ebe3840c06a433ab09_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#98;&#97;&#114;&#123;&#120;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"11\" width=\"10\" style=\"vertical-align: 0px;\"\/> represents the arithmetic mean, <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> is the sample size, and <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3753926091c62342a46ec13bbebace46_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#115;&#117;&#109;&#95;&#123;&#105;&#61;&#49;&#125;&#94;&#123;&#110;&#125;&#32;&#120;&#95;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"60\" style=\"vertical-align: -5px;\"\/> indicates the sum of all observations. This measure provides a concise indication of the central tendency of the data, although it is sensitive to the presence of outliers, which can cause it to deviate significantly from the actual \u201ccenter\u201d of the distribution. <\/p>\n\n<p>Let\u2019s implement this method in our class. <code>DescriptiveStats.php<\/code><\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"&lt;encoded_tag_open \/&gt;?php declare(strict_types=1); namespace Renor\\Statistics; \/** * Class DescriptiveStats * * A lightweight class to perform basic descriptive statistics on numeric datasets. *\/ class DescriptiveStats { \/** * @var float[] Filtered and normalized numeric dataset. *\/ private array $data; \/** * Main constructor. * * @param array $data An array containing the numeric values to be analyzed. * @throws \\InvalidArgumentException If the array is empty or contains no numeric values. *\/ public function __construct(array $data) { \/\/ Filter only numeric values (int or float) and reset array keys $filtered = array_filter($data, 'is_numeric'); $this-&lt;encoded_tag_closed \/&gt;data = array_values($filtered); if (count($this-&lt;encoded_tag_closed \/&gt;data) === 0) { throw new \\InvalidArgumentException('The dataset must contain at least one numeric value.'); } } \/** * Calculates the arithmetic mean of the dataset. * * @return float The arithmetic mean. *\/ public function mean(): float { return array_sum($this-&lt;encoded_tag_closed \/&gt;data) \/ count($this-&lt;encoded_tag_closed \/&gt;data); } }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">&lt;?php<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #C586C0\">declare<\/span><span style=\"color: #D4D4D4\">(strict_types=<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #569CD6\">namespace<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Renor\\Statistics<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Class DescriptiveStats<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * A lightweight class to perform basic descriptive statistics on numeric datasets.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">class<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">DescriptiveStats<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     * <\/span><span style=\"color: #569CD6\">@var<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float[]<\/span><span style=\"color: #6A9955\"> Filtered and normalized numeric dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">array<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$data<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     * Main constructor.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     * <\/span><span style=\"color: #569CD6\">@param<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">array<\/span><span style=\"color: #6A9955\"> $data An array containing the numeric values to be analyzed.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     * <\/span><span style=\"color: #569CD6\">@throws<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #4EC9B0\">\\InvalidArgumentException<\/span><span style=\"color: #6A9955\"> If the array is empty or contains no numeric values.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">__construct<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">array<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$data<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ Filter only numeric values (int or float) and reset array keys<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$filtered<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">array_filter<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$data<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">'is_numeric'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">array_values<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$filtered<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">) === <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">\\InvalidArgumentException<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'The dataset must contain at least one numeric value.'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     * Calculates the arithmetic mean of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The arithmetic mean.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">mean<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">array_sum<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">) \/ <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p>As you can see, we have declared strict_types. This directive enforces PHP to avoid automatic type coercion, which is essential when we want full control over data types.   <\/p>\n\n<p>Since we will accept the data as an array of values, we declare a private property of the class <code>private array $data<\/code>.<\/p>\n\n<p>In the class constructor, we handle retrieving the data passed when instantiating the class to create a new object, verifying that the contents of the array <code>$data<\/code> are numeric, and we place the values inside the property <code>$this-&gt;data<\/code>.<\/p>\n\n<p>In the <code>mean()<\/code> method, we implement the mathematical formula for the mean: we sum all the elements of the passed array and divide by the number of elements, returning the result. <\/p>\n\n<h2 class=\"wp-block-heading\">Median<\/h2>\n\n<p>The median represents the central value of an ordered set of observations and divides the sample into two halves of equal size. Given a series of <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> values <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-5e8319f54f72e7dac2238515c1499b27_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;&#95;&#49;&#44;&#32;&#120;&#95;&#50;&#44;&#32;&#92;&#100;&#111;&#116;&#115;&#44;&#32;&#120;&#95;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"101\" style=\"vertical-align: -4px;\"\/> such that <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-a8df85ae09e9285340b9227eddc7d1ab_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;&#95;&#49;&#32;&#92;&#108;&#101;&#32;&#120;&#95;&#50;&#32;&#92;&#108;&#101;&#32;&#92;&#100;&#111;&#116;&#115;&#32;&#92;&#108;&#101;&#32;&#120;&#95;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"15\" width=\"145\" style=\"vertical-align: -3px;\"\/>: <\/p>\n\n<ul class=\"wp-block-list\">\n<li>If <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> is odd, the median is simply the element in position <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-1450a1ab44bcfe30d8b103b06e9cd5bd_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#102;&#114;&#97;&#99;&#123;&#110;&#43;&#49;&#125;&#123;&#50;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"22\" width=\"26\" style=\"vertical-align: -6px;\"\/>: <br\/><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-74af485cea698cf57cdd7075ad9caf15_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#116;&#101;&#120;&#116;&#123;&#77;&#101;&#100;&#105;&#97;&#110;&#97;&#125;&#32;&#61;&#32;&#120;&#95;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#110;&#43;&#49;&#125;&#123;&#50;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"23\" width=\"125\" style=\"vertical-align: -11px;\"\/><\/li>\n\n\n\n<li>If <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> is even, the median is the arithmetic mean of the two central elements: <br\/><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-91f6e57fe8ee5c52baa255e5225e1cd1_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#116;&#101;&#120;&#116;&#123;&#77;&#101;&#100;&#105;&#97;&#110;&#97;&#125;&#32;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#120;&#95;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#110;&#125;&#123;&#50;&#125;&#125;&#32;&#43;&#32;&#120;&#95;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#110;&#125;&#123;&#50;&#125;&#43;&#49;&#125;&#125;&#123;&#50;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"28\" width=\"158\" style=\"vertical-align: -6px;\"\/><\/li>\n<\/ul>\n\n<p>Unlike the arithmetic mean, the median is robust to outliers, as it depends only on the ordering of the data and not on their magnitude. <\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"  \/** * Calculates the median (50th percentile) of the dataset. * * @return float The median value. *\/ public function median(): float { \/\/ Clone and sort the dataset to avoid mutating the original array $sorted = $this-&lt;encoded_tag_closed \/&gt;data; sort($sorted, SORT_NUMERIC); $count = count($sorted); $mid = intdiv($count, 2); \/\/ If the count is odd, return the middle value if ($count % 2 === 1) { return (float) $sorted[$mid]; } \/\/ If even, return the average of the two central values return ($sorted[$mid - 1] + $sorted[$mid]) \/ 2.0; }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     * Calculates the median (50th percentile) of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The median value.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">     *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">median<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ Clone and sort the dataset to avoid mutating the original array<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">sort<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">, SORT_NUMERIC);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\">   = <\/span><span style=\"color: #DCDCAA\">intdiv<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ If the count is odd, return the middle value<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> % <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ If even, return the average of the two central values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">] + <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\">]) \/ <\/span><span style=\"color: #B5CEA8\">2.0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span><\/code><\/pre><\/div>\n\n<p>In this method, I retrieve the data and sort it. We get the size and calculate the central index using integer division. For example, if we have 7 elements, <code>intdiv(7,2)<\/code> returns 3, which corresponds to the fourth position (remember that arrays in PHP are zero-based!). If the number of values is odd, there is a single perfectly central element, and it is returned. In the case of an even number of values, however, there is not just one central value but two: the ones in positions <code>$mid - 1<\/code> and <code>$mid<\/code>. By definition, the median is the arithmetic mean of these two values. We therefore sum the central elements and divide by 2.0 (using decimal notation to force floating-point division), which returns a float result. This way, the method returns the fiftieth percentile of the sample without modifying the original dataset and in accordance with the statistical definition for both odd and even-length series.        <\/p>\n\n<h2 class=\"wp-block-heading\">Mode<\/h2>\n\n<p>After the mean and the median, the third most commonly used indicator in descriptive statistics is the mode, that is, the value or values that occur most frequently within a set of observations. If we denote by <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-a7ee323bc5a3f73ad5e066b13bed5504_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#102;&#40;&#120;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"34\" style=\"vertical-align: -5px;\"\/> the absolute frequency of a value <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-ede05c264bba0eda080918aaa09c4658_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"10\" style=\"vertical-align: 0px;\"\/> in the sample, the mode is obtained as: <\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-2fa8242aeb4fa25a67e1f100b8cdf195_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#116;&#101;&#120;&#116;&#123;&#77;&#111;&#100;&#97;&#125;&#32;&#61;&#32;&#92;&#111;&#112;&#101;&#114;&#97;&#116;&#111;&#114;&#110;&#97;&#109;&#101;&#42;&#123;&#97;&#114;&#103;&#92;&#44;&#109;&#97;&#120;&#125;&#95;&#123;&#120;&#125;&#92;&#59;&#32;&#102;&#40;&#120;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"179\" style=\"vertical-align: -5px;\"\/>.<\/p>\n\n<p>We can distinguish, based on the input data series:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Unimodal series when only one value has the highest frequency<\/li>\n\n\n\n<li>Multimodal series when two or more values share the highest frequency<\/li>\n\n\n\n<li>Series without a mode when all the values in the series appear only once each<\/li>\n<\/ul>\n\n<p>The mode is particularly useful when the data are categorical or when one wants to highlight concentration around certain integer values. Unlike the mean and the median, it does not measure central tendency but rather the value or values that occur most frequently in the series. It is no coincidence that when a clothing item is \u201cin fashion\u201d it is because, compared to other items in a sales series, it turns out to be the most sold and therefore \u201cthe one most in fashion.\u201d   <\/p>\n\n<p>Let\u2019s therefore add the method to our class:<\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Returns the mode(s) of the dataset. * * If the dataset is multimodal, an array with all modal values is returned. * If every value occurs only once, an empty array is returned (no mode). * * @return float[] list of modal values *\/ public function mode(): array { \/\/ Build a frequency table: value =&lt;encoded_tag_closed \/&gt; occurrences $frequencies = array_count_values($this-&lt;encoded_tag_closed \/&gt;data); \/\/ Determine the highest frequency $maxFrequency = max($frequencies); \/\/ If every value appears only once, there is no mode if ($maxFrequency === 1) { return []; } \/\/ Collect all values that share the highest frequency $modes = []; foreach ($frequencies as $value =&lt;encoded_tag_closed \/&gt; $count) { if ($count === $maxFrequency) { \/\/ Cast to float so that return type is consistent $modes[] = (float) $value; } } sort($modes, SORT_NUMERIC); \/\/ return modes in ascending order return $modes; }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Returns the mode(s) of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * If the dataset is multimodal, an array with all modal values is returned.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * If every value occurs only once, an empty array is returned (no mode).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float[]<\/span><span style=\"color: #6A9955\"> list of modal values<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">mode<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">array<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Build a frequency table: value =&gt; occurrences<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$frequencies<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">array_count_values<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Determine the highest frequency<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$maxFrequency<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">max<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$frequencies<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ If every value appears only once, there is no mode<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$maxFrequency<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> [];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Collect all values that share the highest frequency<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$modes<\/span><span style=\"color: #D4D4D4\"> = [];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$frequencies<\/span><span style=\"color: #D4D4D4\"> as <\/span><span style=\"color: #9CDCFE\">$value<\/span><span style=\"color: #D4D4D4\"> =&gt; <\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #9CDCFE\">$maxFrequency<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #6A9955\">\/\/ Cast to float so that return type is consistent<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">$modes<\/span><span style=\"color: #D4D4D4\">[] = (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #9CDCFE\">$value<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">sort<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$modes<\/span><span style=\"color: #D4D4D4\">, SORT_NUMERIC); <\/span><span style=\"color: #6A9955\">\/\/ return modes in ascending order<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$modes<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p><br\/><br\/><code>array_count_values()<\/code> It scans the entire dataset and returns an associative array where the <strong>key<\/strong> is the observed value and the <strong>value<\/strong> is the number of times it occurs. This is a quick way to calculate <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-a7ee323bc5a3f73ad5e066b13bed5504_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#102;&#40;&#120;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"34\" style=\"vertical-align: -5px;\"\/> for each <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-ede05c264bba0eda080918aaa09c4658_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"10\" style=\"vertical-align: 0px;\"\/>.<br\/>With <code>max($frequencies)<\/code>, we obtain the highest number of occurrences present in the table; this corresponds to the value of <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-1ccf759ba917b35db6276661cda96893_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#109;&#97;&#120;&#32;&#102;&#40;&#120;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"70\" style=\"vertical-align: -5px;\"\/> in the mathematical definition.<br\/>If the maximum frequency is 1, it means that each observation is unique. In this case, the method returns an empty array to indicate that no modal value exists.<br\/>We iterate over the frequency table: for each key whose count equals the maximum frequency, we add that value (cast to float) to the array <code>$modes<\/code>. In this way, <strong>all<\/strong> modal values are included in the case of multimodality.<br\/>Before returning the result, <code>sort($modes, SORT_NUMERIC)<\/code> ensures that the modes are sorted in ascending order, making the output more predictable.   <\/p>\n\n<p>In this way, we have covered all possible scenarios: unimodal, multimodal, and without a mode. <\/p>\n\n<h2 class=\"wp-block-heading\">Geometric mean<\/h2>\n\n<p>The <strong>geometric mean<\/strong> is the most appropriate measure of central tendency when the data represent <em>growth rates<\/em> or <em>ratios<\/em> (for example, percentage returns, variation indices, logarithmic scales).<\/p>\n\n<p>Given a series of <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> <strong>strictly positive values<\/strong> <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-5e8319f54f72e7dac2238515c1499b27_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;&#95;&#49;&#44;&#32;&#120;&#95;&#50;&#44;&#32;&#92;&#100;&#111;&#116;&#115;&#44;&#32;&#120;&#95;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"101\" style=\"vertical-align: -4px;\"\/>, the geometric mean <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-30a79c32f18567063fe44716929e7ced_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#71;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"14\" style=\"vertical-align: 0px;\"\/> is defined as:<\/p>\n\n<p><br\/><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-a4742ffe66183a651acae6a09c623c28_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#71;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#66;&#105;&#103;&#108;&#40;&#32;&#92;&#112;&#114;&#111;&#100;&#95;&#123;&#105;&#61;&#49;&#125;&#94;&#123;&#110;&#125;&#32;&#120;&#95;&#105;&#32;&#92;&#66;&#105;&#103;&#114;&#41;&#94;&#123;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#110;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"39\" width=\"137\" style=\"vertical-align: -11px;\"\/><\/p>\n\n<p>or, in a numerically more stable logarithmic form:<\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-d61959aa5fbed45f159915591eb7e023_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#108;&#110;&#32;&#71;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#110;&#125;&#32;&#92;&#115;&#117;&#109;&#95;&#123;&#105;&#61;&#49;&#125;&#94;&#123;&#110;&#125;&#32;&#92;&#108;&#110;&#32;&#120;&#95;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"22\" width=\"158\" style=\"vertical-align: -6px;\"\/>.<\/p>\n\n<p><br\/>This quantity corresponds to the \u201caverage\u201d growth factor which, applied n times in sequence, yields the same result as the actual product of the values.<\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Calculates the geometric mean of the dataset. * * @throws \\DomainException If any value is zero or negative. * @return float The geometric mean. *\/ public function geometricMean(): float { \/\/ The geometric mean is defined only for strictly positive numbers. foreach ($this-&lt;encoded_tag_closed \/&gt;data as $value) { if ($value &lt;encoded_tag_open \/&gt;= 0) { throw new \\DomainException('Geometric mean requires all values to be greater than zero.'); } } \/\/ Use logarithms for numerical stability: exp( (1\/n) * sum(log(x_i)) ) $logSum = array_sum(array_map('log', $this-&lt;encoded_tag_closed \/&gt;data)); return exp($logSum \/ count($this-&lt;encoded_tag_closed \/&gt;data)); }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Calculates the geometric mean of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@throws<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #6A9955\"> If any value is zero or negative.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The geometric mean.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">geometricMean<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ The geometric mean is defined only for strictly positive numbers.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\"> as <\/span><span style=\"color: #9CDCFE\">$value<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$value<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'Geometric mean requires all values to be greater than zero.'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Use logarithms for numerical stability: exp( (1\/n) * sum(log(x_i)) )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$logSum<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">array_sum<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">array_map<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'log'<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">exp<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$logSum<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p><br\/><br\/>Since the geometric mean is only defined for positive numbers, the method scans the dataset and throws a DomainException if it encounters values \u2264 0. This prevents mathematically incorrect (or complex) results.<br\/>Instead of directly calculating the product (which could easily overflow), we convert each value using <code>log()<\/code>, sum the logarithms, and divide by <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/>. Based on the properties of logarithms:   <br\/><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-43f802e186e975abe5f7cfa92e0d7040_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#108;&#110;&#92;&#33;&#92;&#66;&#105;&#103;&#108;&#40;&#92;&#112;&#114;&#111;&#100;&#32;&#120;&#95;&#105;&#92;&#66;&#105;&#103;&#114;&#41;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#115;&#117;&#109;&#32;&#92;&#108;&#110;&#32;&#120;&#95;&#105;\" title=\"Rendered by QuickLaTeX.com\" height=\"32\" width=\"156\" style=\"vertical-align: -11px;\"\/><br\/><br\/>By applying <code>exp()<\/code> to the average of the logarithms, we obtain the geometric mean.<br\/><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-bfbde60fff002baebb36779f76f72332_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#71;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#101;&#120;&#112;&#92;&#33;&#92;&#66;&#105;&#103;&#108;&#40;&#92;&#116;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#110;&#125;&#92;&#115;&#117;&#109;&#32;&#92;&#108;&#110;&#32;&#120;&#95;&#105;&#92;&#66;&#105;&#103;&#114;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"32\" width=\"160\" style=\"vertical-align: -11px;\"\/><\/p>\n\n<h2 class=\"wp-block-heading\">Harmonic mean<\/h2>\n\n<p>The <strong>harmonic mean<\/strong> is the most appropriate measure of central tendency when the data represent <strong>speeds, ratios, or fractions<\/strong>\u2014for example, kilometers per hour traveled at different paces, average cost per unit, or average return on investments calculated as \u201cunits per euro.\u201d<\/p>\n\n<p>Given a series of <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> positive values <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-5e8319f54f72e7dac2238515c1499b27_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;&#95;&#49;&#44;&#32;&#120;&#95;&#50;&#44;&#32;&#92;&#100;&#111;&#116;&#115;&#44;&#32;&#120;&#95;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"101\" style=\"vertical-align: -4px;\"\/> (no value can be zero, as it would appear in the denominator), the harmonic mean <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-379db1fc1f84b7ce56b92463183097f9_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#72;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"16\" style=\"vertical-align: 0px;\"\/> is defined as:<br\/><br\/><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3d6ce62f9aca45ea9d0e009d4e105ee4_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#72;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#110;&#125;&#123;&#92;&#100;&#105;&#115;&#112;&#108;&#97;&#121;&#115;&#116;&#121;&#108;&#101;&#92;&#115;&#117;&#109;&#95;&#123;&#105;&#61;&#49;&#125;&#94;&#123;&#110;&#125;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#120;&#95;&#105;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"60\" width=\"101\" style=\"vertical-align: -47px;\"\/><\/p>\n\n<p>In other words, it is calculated as the <strong>inverse of the arithmetic mean<\/strong> of the reciprocals. Compared to the arithmetic mean, the harmonic mean gives <strong>more weight to smaller values<\/strong>: it is therefore valuable when one wishes to strongly penalize poorer performances (e.g., the average time to travel one kilometer over multiple segments at different speeds). <\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Calculates the harmonic mean of the dataset. * * @throws \\DomainException If any value is zero or negative. * @return float The harmonic mean. *\/ public function harmonicMean(): float { \/\/ Harmonic mean is defined only for strictly positive numbers. foreach ($this-&lt;encoded_tag_closed \/&gt;data as $value) { if ($value &lt;encoded_tag_open \/&gt;= 0) { throw new \\DomainException('Harmonic mean requires all values to be greater than zero.'); } } $inverseSum = array_sum(array_map( static fn (float $v): float =&lt;encoded_tag_closed \/&gt; 1.0 \/ $v, $this-&lt;encoded_tag_closed \/&gt;data )); return count($this-&lt;encoded_tag_closed \/&gt;data) \/ $inverseSum; }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Calculates the harmonic mean of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@throws<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #6A9955\"> If any value is zero or negative.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The harmonic mean.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">harmonicMean<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Harmonic mean is defined only for strictly positive numbers.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\"> as <\/span><span style=\"color: #9CDCFE\">$value<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$value<\/span><span style=\"color: #D4D4D4\"> &lt;= <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'Harmonic mean requires all values to be greater than zero.'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$inverseSum<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">array_sum<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">array_map<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">static<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">fn<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$v<\/span><span style=\"color: #D4D4D4\">): <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> =&gt; <\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #9CDCFE\">$v<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    ));<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">) \/ <\/span><span style=\"color: #9CDCFE\">$inverseSum<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p>First, a domain check is performed: any value less than or equal to zero triggers a DomainException, otherwise the result would be undefined or become infinite. Then, a sum of the reciprocals is computed: <code>array_map()<\/code> calculates the reciprocal of each element, <code>array_sum()<\/code> sums them.<br\/>The direct formula divides the number of observations <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> by the obtained sum, according to the mathematical definition.  <\/p>\n\n<h2 class=\"wp-block-heading\">Truncated mean (or trimmed mean)<\/h2>\n\n<p>When a sample contains extreme <strong>outliers<\/strong> that risk distorting the arithmetic mean, an elegant solution is the <strong>truncated mean<\/strong> (or <em>trimmed mean<\/em>).<\/p>\n\n<p>A percentage <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3bf85f1087e9fbed3a319341134ac1a2_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#112;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"10\" style=\"vertical-align: -4px;\"\/>% (typically 5% or 10%) is chosen, the sample is sorted, and the first <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3422b6bb5c160593658b7c39425d9880_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#107;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"9\" style=\"vertical-align: 0px;\"\/> smallest and the last <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3422b6bb5c160593658b7c39425d9880_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#107;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"9\" style=\"vertical-align: 0px;\"\/> largest observations are <strong>discarded<\/strong>, where:<\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-ee3395887d7d468db47e03e3b0a83719_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#98;&#97;&#114;&#123;&#120;&#125;&#123;&#92;&#116;&#101;&#120;&#116;&#123;&#116;&#114;&#105;&#109;&#125;&#125;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#92;&#44;&#110;&#45;&#50;&#107;&#92;&#44;&#125;&#32;&#92;&#115;&#117;&#109;&#123;&#105;&#61;&#107;&#43;&#49;&#125;&#94;&#123;&#92;&#44;&#110;&#45;&#107;&#125;&#32;&#120;&#95;&#123;&#40;&#105;&#41;&#125;&#32;\" title=\"Rendered by QuickLaTeX.com\" height=\"24\" width=\"267\" style=\"vertical-align: -8px;\"\/>.<br\/><br\/>This way, a measure of central tendency is obtained that is <strong>more robust<\/strong> than the arithmetic mean but less drastic than the median.<\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Calculates the trimmed mean of the dataset. * * @param float $percent Percentage (0\u201350) of data to trim at each tail. * @throws \\DomainException If $percent is out of range or removes all data. * @return float The trimmed mean. *\/ public function trimmedMean(float $percent): float { if ($percent &lt;encoded_tag_open \/&gt; 0.0 || $percent &lt;encoded_tag_closed \/&gt;= 50.0) { throw new \\DomainException('Percent must be in the range 0 &lt;encoded_tag_open \/&gt;= p &lt;encoded_tag_open \/&gt; 50.'); } $count = count($this-&lt;encoded_tag_closed \/&gt;data); if ($count &lt;encoded_tag_open \/&gt; 3) { \/\/ Too few values to trim meaningfully; fall back to arithmetic mean return $this-&lt;encoded_tag_closed \/&gt;mean(); } \/\/ Clone and sort to preserve original order $sorted = $this-&lt;encoded_tag_closed \/&gt;data; sort($sorted, SORT_NUMERIC); \/\/ Number of elements to trim from each end $k = (int) floor($count * $percent \/ 100.0); \/\/ Ensure at least one value remains if ($k * 2 &lt;encoded_tag_closed \/&gt;= $count) { throw new \\DomainException('Trim percentage removes all data.'); } $trimmed = array_slice($sorted, $k, $count - 2 * $k); return array_sum($trimmed) \/ count($trimmed); }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Calculates the trimmed mean of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@param<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> $percent Percentage (0\u201350) of data to trim at each tail.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@throws<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #6A9955\"> If $percent is out of range or removes all data.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The trimmed mean.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">trimmedMean<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$percent<\/span><span style=\"color: #D4D4D4\">): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$percent<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\"> || <\/span><span style=\"color: #9CDCFE\">$percent<\/span><span style=\"color: #D4D4D4\"> &gt;= <\/span><span style=\"color: #B5CEA8\">50.0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'Percent must be in the range 0 &lt;= p &lt; 50.'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ Too few values to trim meaningfully; fall back to arithmetic mean<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">mean<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Clone and sort to preserve original order<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">sort<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">, SORT_NUMERIC);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Number of elements to trim from each end<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$k<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #DCDCAA\">floor<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">$percent<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #B5CEA8\">100.0<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Ensure at least one value remains<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$k<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> &gt;= <\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'Trim percentage removes all data.'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$trimmed<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">array_slice<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">$k<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">$k<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">array_sum<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$trimmed<\/span><span style=\"color: #D4D4D4\">) \/ <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$trimmed<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p>The method begins by verifying that the chosen trimming percentage makes sense: it must be greater than or equal to zero and strictly less than fifty, otherwise an exception is thrown; if, for example, we were to request the removal of 60% of the data from each tail, there would be nothing left to average.<\/p>\n\n<p>If the sample contains fewer than three observations, the function considers trimming meaningless and simply returns the arithmetic mean: with two values, removing even one would eliminate half the data, while with only one there is nothing to trim.<\/p>\n\n<p>The process then proceeds by <strong>cloning<\/strong> the original array and <strong>sorting<\/strong> it in ascending order; cloning preserves the order in which the data was provided to the object, while sorting is essential because trimming is applied starting from the extremes of the distribution.<\/p>\n\n<p>The number of elements to discard at each tail, denoted by <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3422b6bb5c160593658b7c39425d9880_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#107;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"9\" style=\"vertical-align: 0px;\"\/>, is obtained by multiplying the sample size by the requested percentage and rounding down; for example, if we have ten values and want a 10% trimmed mean, we will remove one element from the beginning and one from the end.<\/p>\n\n<p>Before proceeding, the method checks that \u201ctwice <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3422b6bb5c160593658b7c39425d9880_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#107;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"9\" style=\"vertical-align: 0px;\"\/>\u201d is not equal to or greater than the length of the array: if it were, the trimming would remove all the data and the mean would no longer make sense; in such case, an additional exception is thrown.<\/p>\n\n<p>Once this check is passed, <code>array_slice()<\/code> extracts the central portion that remains after discarding the <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3422b6bb5c160593658b7c39425d9880_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#107;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"9\" style=\"vertical-align: 0px;\"\/> smallest and <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3422b6bb5c160593658b7c39425d9880_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#107;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"9\" style=\"vertical-align: 0px;\"\/> largest values; the arithmetic mean is then calculated on this subset, which is precisely the desired <strong>trimmed mean<\/strong>.<\/p>\n\n<p>The function thus returns a measure of central tendency that is more <strong>robust<\/strong> than the classic mean: the outliers, removed before the calculation, can no longer pull the result toward extreme values.<\/p>\n\n<h2 class=\"wp-block-heading\">Range<\/h2>\n\n<p>The <strong>range<\/strong> is the simplest measure of dispersion: it indicates the total spread of the observed values, that is, the distance between the minimum and maximum extremes of the sample. If we denote <\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3b118489e45d1027030f5b15276e5196_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;&#95;&#123;&#92;&#109;&#105;&#110;&#125;&#32;&#61;&#32;&#92;&#109;&#105;&#110;&#40;&#120;&#95;&#49;&#44;&#92;&#100;&#111;&#116;&#115;&#44;&#120;&#95;&#110;&#41;&#32;&#92;&#113;&#117;&#97;&#100;&#92;&#116;&#101;&#120;&#116;&#123;&#101;&#125;&#92;&#113;&#117;&#97;&#100;&#32;&#120;&#95;&#123;&#92;&#109;&#97;&#120;&#125;&#32;&#61;&#32;&#92;&#109;&#97;&#120;&#40;&#120;&#95;&#49;&#44;&#92;&#100;&#111;&#116;&#115;&#44;&#120;&#95;&#110;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"403\" style=\"vertical-align: -5px;\"\/>,<\/p>\n\n<p>then the range <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-dae6bae3dcdac4629730754352c5e329_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#82;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"14\" style=\"vertical-align: 0px;\"\/> is defined as<\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-d399b72f8b0465415f1e24a72be4f993_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#82;&#32;&#61;&#32;&#120;&#95;&#123;&#92;&#109;&#97;&#120;&#125;&#32;&#92;&#59;&#45;&#92;&#59;&#32;&#120;&#95;&#123;&#92;&#109;&#105;&#110;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"15\" width=\"138\" style=\"vertical-align: -3px;\"\/>.<\/p>\n\n<p>Although it is sensitive to outliers (the same value that affects the maximum or minimum also affects the range), this measure provides an immediate indication of the distribution\u2019s <strong>spread<\/strong> and is often reported alongside the mean or median to give a quick overview of overall dispersion.<\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Calculates the range (max \u2013 min) of the dataset. * * @return float The range of the data. *\/ public function range(): float { \/\/ min() e max() sono O(n) ma il dataset \u00e8 gi\u00e0 in memoria: soluzione lineare return max($this-&lt;encoded_tag_closed \/&gt;data) - min($this-&lt;encoded_tag_closed \/&gt;data); }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Calculates the range (max \u2013 min) of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The range of the data.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">range<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ min() e max() sono O(n) ma il dataset \u00e8 gi\u00e0 in memoria: soluzione lineare<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">max<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">) - <\/span><span style=\"color: #DCDCAA\">min<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p>As can be seen, the method is very straightforward. It invokes the native PHP functions <code>max()<\/code> and <code>min()<\/code>, which each perform a single linear scan of the array to identify the largest and smallest values, respectively. Subtracting the minimum from the maximum yields the total spread of the sample; the result is returned as a float, consistent with the other methods in the class.   <\/p>\n\n<h2 class=\"wp-block-heading\">Quartiles and interquartile range (IQR)<\/h2>\n\n<p>To describe the dispersion of a sample more robustly than with the simple range, <strong>quartiles<\/strong> are used:<\/p>\n\n<ul class=\"wp-block-list\">\n<li><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-6b6b12b50fe43a209ecce557539ee185_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"20\" style=\"vertical-align: -4px;\"\/> \u2013 25th percentile (first quartile)<\/li>\n\n\n\n<li><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-7a8f7f7bc05736504761c873bfd99aa1_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#50;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"21\" style=\"vertical-align: -4px;\"\/> \u2013 50th percentile (median)<\/li>\n\n\n\n<li><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-6cef68a5946963445c5d51e5093bd228_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#51;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"21\" style=\"vertical-align: -4px;\"\/> \u2013 75th percentile (third quartile)<\/li>\n<\/ul>\n\n<p>The interquartile range is defined as <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b7e8e27ef6cdf0eb6f547ea71a0510cb_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#116;&#101;&#120;&#116;&#123;&#73;&#81;&#82;&#125;&#32;&#61;&#32;&#81;&#95;&#51;&#32;&#45;&#32;&#81;&#95;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"120\" style=\"vertical-align: -4px;\"\/> and represents the spread of the central half of the data. It is not very sensitive to outliers because it is based only on the values between the 25th and 75th percentiles of the distribution.  <\/p>\n\n<p>A classic use of the IQR is outlier detection using Tukey\u2019s method (values less than <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-f2de8fe42732eb0aaaed68ccf31b0510_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#49;&#32;&#45;&#32;&#49;&#46;&#53;&#32;&#92;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#73;&#81;&#82;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"17\" width=\"102\" style=\"vertical-align: -4px;\"\/> or greater than <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-35a5d5e74a4c88ba8ee2a6ffef76e3c2_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#51;&#32;&#43;&#32;&#49;&#46;&#53;&#32;&#92;&#44;&#32;&#92;&#116;&#101;&#120;&#116;&#123;&#73;&#81;&#82;&#125;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"19\" width=\"108\" style=\"vertical-align: -5px;\"\/>.<\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Returns an array with the first, second (median) and third quartile. * * Method: \"Tukey hinges\". * - Sort the dataset. * - For Q1 and Q3, exclude the median when the sample size is odd. * * @return float[] [Q1, Q2, Q3] in ascending order. *\/ public function quartiles(): array { $sorted = $this-&lt;encoded_tag_closed \/&gt;data; sort($sorted, SORT_NUMERIC); $n = count($sorted); if ($n === 1) { return [$sorted[0], $sorted[0], $sorted[0]]; } $mid = intdiv($n, 2); \/\/ Median (Q2) $q2 = ($n % 2 === 0) ? ($sorted[$mid - 1] + $sorted[$mid]) \/ 2.0 : (float) $sorted[$mid]; \/\/ Lower half (exclude median if n is odd) $lower = array_slice($sorted, 0, $mid); \/\/ Upper half (exclude median if n is odd) $upper = array_slice($sorted, ($n % 2 === 0) ? $mid : $mid + 1); \/\/ Q1 and Q3 are medians of the two halves $q1 = $this-&lt;encoded_tag_closed \/&gt;medianOfArray($lower); $q3 = $this-&lt;encoded_tag_closed \/&gt;medianOfArray($upper); return [$q1, $q2, $q3]; } \/** * Calculates the interquartile range (Q3 \u2013 Q1). * * @return float The interquartile range. *\/ public function iqr(): float { [$q1, , $q3] = $this-&lt;encoded_tag_closed \/&gt;quartiles(); return $q3 - $q1; } \/* ---------- Helper ---------- *\/ \/** * Median of a pre-sorted array (helper for quartiles). * * @param float[] $arr Sorted numeric array. * @return float Median value. *\/ private function medianOfArray(array $arr): float { $count = count($arr); if ($count === 0) { throw new \\LogicException('Cannot compute median of an empty array.'); } $mid = intdiv($count, 2); return ($count % 2 === 0) ? ($arr[$mid - 1] + $arr[$mid]) \/ 2.0 : (float) $arr[$mid]; }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Returns an array with the first, second (median) and third quartile.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Method: \"Tukey hinges\".<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *  - Sort the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *  - For Q1 and Q3, exclude the median when the sample size is odd.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float[]<\/span><span style=\"color: #6A9955\"> [Q1, Q2, Q3] in ascending order.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">quartiles<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">array<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">sort<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">, SORT_NUMERIC);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> [<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">], <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">intdiv<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ Median (Q2)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$q2<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> % <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            ? (<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">] + <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\">]) \/ <\/span><span style=\"color: #B5CEA8\">2.0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            : (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ Lower half (exclude median if n is odd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$lower<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">array_slice<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ Upper half (exclude median if n is odd)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$upper<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">array_slice<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">, (<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> % <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) ? <\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\"> : <\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ Q1 and Q3 are medians of the two halves<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$q1<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">medianOfArray<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$lower<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$q3<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">medianOfArray<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$upper<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> [<\/span><span style=\"color: #9CDCFE\">$q1<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">$q2<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">$q3<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Calculates the interquartile range (Q3 \u2013 Q1).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The interquartile range.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">iqr<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    [<\/span><span style=\"color: #9CDCFE\">$q1<\/span><span style=\"color: #D4D4D4\">, , <\/span><span style=\"color: #9CDCFE\">$q3<\/span><span style=\"color: #D4D4D4\">] = <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">quartiles<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$q3<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">$q1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #6A9955\">\/* ---------- Helper ---------- *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Median of a pre-sorted array (helper for quartiles).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@param<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float[]<\/span><span style=\"color: #6A9955\"> $arr Sorted numeric array.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> Median value.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">private<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">medianOfArray<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">array<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$arr<\/span><span style=\"color: #D4D4D4\">): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$arr<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">\\LogicException<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'Cannot compute median of an empty array.'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">intdiv<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$count<\/span><span style=\"color: #D4D4D4\"> % <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        ? (<\/span><span style=\"color: #9CDCFE\">$arr<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">] + <\/span><span style=\"color: #9CDCFE\">$arr<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\">]) \/ <\/span><span style=\"color: #B5CEA8\">2.0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        : (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #9CDCFE\">$arr<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$mid<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p>When the <code>quartiles()<\/code> method is called, the first thing it does is create a copy of the internal data and sort it in ascending order; this copy preserves the original order provided by the user and allows working with a monotonically ordered vector, which is a necessary prerequisite for identifying quartiles. Immediately afterward, the variable <code>$n<\/code> stores the sample size, and <code>$mid<\/code> represents the central index calculated via integer division. With these two pieces of information, the median of the entire sample is determined, which becomes the second quartile <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-7a8f7f7bc05736504761c873bfd99aa1_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#50;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"21\" style=\"vertical-align: -4px;\"\/>; if the number of observations is even, the median is the arithmetic mean of the two central values, whereas in the odd case, it coincides with the value at the central position.  <\/p>\n\n<p>Once <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-7a8f7f7bc05736504761c873bfd99aa1_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#50;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"21\" style=\"vertical-align: -4px;\"\/> is known, the sorted array is split into two halves. If the sample size is odd, the median must not be included in either the lower or upper part, so the function <code>array_slice<\/code> explicitly excludes it; if it is even, the division occurs exactly in half. At this point, the outer quartiles come into play: to calculate <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-6b6b12b50fe43a209ecce557539ee185_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"20\" style=\"vertical-align: -4px;\"\/> and <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-6cef68a5946963445c5d51e5093bd228_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#51;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"21\" style=\"vertical-align: -4px;\"\/>, no new object is created\u2014rather, the private helper <code>medianOfArray<\/code> is invoked on the two already sorted halves. This small routine receives a vector, counts its elements, determines the central index, and returns the median using the same logic as before; all of this remains confined within the class, keeping the public interface clean and avoiding any code duplication.   <\/p>\n\n<p>The <code>quartiles()<\/code> method finally returns an array with the three values <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-2a57835ccc4419c852fb77d64952d763_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#91;&#81;&#95;&#49;&#44;&#32;&#81;&#95;&#50;&#44;&#32;&#81;&#95;&#51;&#93;\" title=\"Rendered by QuickLaTeX.com\" height=\"18\" width=\"87\" style=\"vertical-align: -5px;\"\/> in ascending order. Its counterpart, <code>iqr()<\/code>, simply unpacks that array, subtracts <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-6b6b12b50fe43a209ecce557539ee185_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"20\" style=\"vertical-align: -4px;\"\/> from <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-6cef68a5946963445c5d51e5093bd228_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#81;&#95;&#51;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"21\" style=\"vertical-align: -4px;\"\/>, and returns the interquartile range, providing in a single call the most robust measure of dispersion in the class. <\/p>\n\n<p>In this setup, the logic for computing the median remains centralized within the private helper, and is reused both for quartiles and, implicitly, for any other internal functionality that might need to calculate a median on a sorted subset. Meanwhile, the public API continues to offer self-explanatory and easy-to-understand methods for anyone integrating your library.<\/p>\n\n<h2 class=\"wp-block-heading\">Variance<\/h2>\n\n<p>To measure how much the values deviate from their central tendency, <strong>variance<\/strong> is introduced, which calculates the mean of the squared deviations from the arithmetic mean. Given <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> observations <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-08f4f7c471a86ab23d63ecf2d1c0071b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;&#95;&#49;&#44;&#32;&#120;&#95;&#50;&#44;&#32;&#92;&#100;&#111;&#116;&#115;&#44;&#32;&#120;&#95;&#110;&#32;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"101\" style=\"vertical-align: -4px;\"\/>with mean <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-20ebc7ea21d727ebe3840c06a433ab09_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#98;&#97;&#114;&#123;&#120;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"11\" width=\"10\" style=\"vertical-align: 0px;\"\/>, the <strong>population variance<\/strong> is defined as: <\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3cde5d7135396b988fc10797bf8b06e4_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#115;&#105;&#103;&#109;&#97;&#94;&#123;&#50;&#125;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#110;&#125;&#92;&#115;&#117;&#109;&#95;&#123;&#105;&#61;&#49;&#125;&#94;&#123;&#110;&#125;&#40;&#120;&#95;&#105;&#32;&#45;&#32;&#92;&#98;&#97;&#114;&#123;&#120;&#125;&#41;&#94;&#123;&#50;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"22\" width=\"177\" style=\"vertical-align: -6px;\"\/><\/p>\n\n<p>If instead the data represent a <strong>sample<\/strong> drawn from a larger population, the correct estimator (sample variance) divides by <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-88ba1a69ceedf1a3a91b958bb253b927_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;&#32;&#8722;&#32;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"19\" style=\"vertical-align: 0px;\"\/>:<\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-932ecac38eb830d655be06b4360392dd_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#115;&#94;&#123;&#50;&#125;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#110;&#45;&#49;&#125;&#92;&#115;&#117;&#109;&#95;&#123;&#105;&#61;&#49;&#125;&#94;&#123;&#110;&#125;&#40;&#120;&#95;&#105;&#32;&#45;&#32;&#92;&#98;&#97;&#114;&#123;&#120;&#125;&#41;&#94;&#123;&#50;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"22\" width=\"192\" style=\"vertical-align: -6px;\"\/><\/p>\n\n<p>Variance returns a <strong>quadratic<\/strong> value: it is always non-negative and increases rapidly as deviations grow. For this reason, it is often used in conjunction with its square root (standard deviation) to return to the same units of measurement as the data.<\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Calculates the variance of the dataset. * * @param bool $sample If true, uses (n-1) in the denominator (sample variance). * If false, uses n (population variance). * @return float The variance value. *\/ public function variance(bool $sample = false): float { $n = count($this-&lt;encoded_tag_closed \/&gt;data); \/\/ For a single value, population variance is 0, sample variance is undefined if ($n &lt;encoded_tag_open \/&gt; 2 &amp;&amp; $sample) { throw new \\DomainException('Sample variance requires at least two observations.'); } if ($n === 1) { return 0.0; } $mean = $this-&lt;encoded_tag_closed \/&gt;mean(); $sumSquares = 0.0; foreach ($this-&lt;encoded_tag_closed \/&gt;data as $v) { $diff = $v - $mean; $sumSquares += $diff * $diff; } $denominator = $sample ? ($n - 1) : $n; return $sumSquares \/ $denominator; }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Calculates the variance of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@param<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">bool<\/span><span style=\"color: #6A9955\"> $sample If true, uses (n-1) in the denominator (sample variance).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *                     If false, uses n (population variance).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The variance value.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">variance<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">bool<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$sample<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ For a single value, population variance is 0, sample variance is undefined<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> &amp;&amp; <\/span><span style=\"color: #9CDCFE\">$sample<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'Sample variance requires at least two observations.'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$mean<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">mean<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$sumSquares<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\"> as <\/span><span style=\"color: #9CDCFE\">$v<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$diff<\/span><span style=\"color: #D4D4D4\">        = <\/span><span style=\"color: #9CDCFE\">$v<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">$mean<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$sumSquares<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #9CDCFE\">$diff<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">$diff<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$denominator<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$sample<\/span><span style=\"color: #D4D4D4\"> ? (<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) : <\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$sumSquares<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #9CDCFE\">$denominator<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p><br\/>The method receives a flag indicating whether to calculate the population variance or the sample estimator. It begins by evaluating the dataset size: with only one value, the population variance is by definition zero, whereas the sample variance does not exist and an exception is thrown. Once the mean is known, the loop traverses each observation, subtracts the mean, squares the deviation, and accumulates it. After the summation is complete, the division is performed by <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> or <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-88ba1a69ceedf1a3a91b958bb253b927_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;&#32;&#8722;&#32;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"19\" style=\"vertical-align: 0px;\"\/> depending on the specified context, thus returning the desired measure of dispersion.   <\/p>\n\n<h2 class=\"wp-block-heading\">Standard deviation<\/h2>\n\n<p><br\/>The <strong>standard deviation<\/strong> is simply the square root of the variance: it serves to bring the measure of dispersion back to the same units as the original data. If variance indicates \u201chow many squared units\u201d the observations deviate on average from their mean, the standard deviation expresses that deviation in linear units, making it much more intuitive for a non-specialist reader. For the population, it is obtained as <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-084a79d5a7bbe330f12ebed3c76aa066_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#115;&#105;&#103;&#109;&#97;&#32;&#61;&#32;&#92;&#115;&#113;&#114;&#116;&#123;&#92;&#115;&#105;&#103;&#109;&#97;&#94;&#123;&#50;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"18\" width=\"68\" style=\"vertical-align: -1px;\"\/> while in the sample case it is <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-2aa1eaecb6b446e07c4b2edf8fa49880_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#115;&#32;&#61;&#32;&#92;&#115;&#113;&#114;&#116;&#123;&#115;&#94;&#123;&#50;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"18\" width=\"64\" style=\"vertical-align: -1px;\"\/>. Small standard deviation values indicate a distribution concentrated around the mean; large values indicate widely dispersed data.   <\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Calculates the standard deviation of the dataset. * * @param bool $sample If true, returns the sample standard deviation (n-1 in the denominator). * If false, returns the population standard deviation. * @return float The standard deviation. *\/ public function standardDeviation(bool $sample = false): float { return sqrt($this-&lt;encoded_tag_closed \/&gt;variance($sample)); }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Calculates the standard deviation of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@param<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">bool<\/span><span style=\"color: #6A9955\"> $sample If true, returns the sample standard deviation (n-1 in the denominator).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *                     If false, returns the population standard deviation.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The standard deviation.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">standardDeviation<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">bool<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$sample<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">false<\/span><span style=\"color: #D4D4D4\">): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">sqrt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">variance<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sample<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p><br\/>The method contains no additional logic: it simply calls <code>variance()<\/code> with the same flag and returns its square root, delegating all calculation and domain checks to the already tested algorithm.<\/p>\n\n<h2 class=\"wp-block-heading\">Standard error of the mean<\/h2>\n\n<p>When we observe only a sample from the population, the sample mean is an estimate subject to fluctuations: the smaller the sample, the more the estimate may vary from one sample to another. The <strong>standard error of the mean<\/strong> (<em>SEM<\/em>) precisely quantifies this expected variability. If s is the sample standard deviation and n is the sample size, the standard error is calculated as  <\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-01ae367d3efe370932420a9b723937f4_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#116;&#101;&#120;&#116;&#123;&#83;&#69;&#77;&#125;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#115;&#125;&#123;&#92;&#115;&#113;&#114;&#116;&#123;&#110;&#125;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"24\" width=\"94\" style=\"vertical-align: -11px;\"\/>.<\/p>\n\n<p>A small SEM indicates that the mean calculated from that sample is likely close to the true population mean; a large SEM suggests greater uncertainty. The SEM is also the basis for constructing confidence intervals for the mean. <\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Calculates the standard error of the mean (SEM) of the dataset. * * SEM = sample standard deviation \/ sqrt(n) * Requires at least two observations. * * @throws \\DomainException If the dataset size is less than 2. * @return float The standard error of the mean. *\/ public function standardError(): float { $n = count($this-&lt;encoded_tag_closed \/&gt;data); if ($n &lt;encoded_tag_open \/&gt; 2) { throw new \\DomainException('Standard error requires at least two observations.'); } return $this-&lt;encoded_tag_closed \/&gt;standardDeviation(true) \/ sqrt($n); }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Calculates the standard error of the mean (SEM) of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * SEM = sample standard deviation \/ sqrt(n)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Requires at least two observations.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@throws<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #6A9955\"> If the dataset size is less than 2.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The standard error of the mean.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">standardError<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'Standard error requires at least two observations.'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">standardDeviation<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">true<\/span><span style=\"color: #D4D4D4\">) \/ <\/span><span style=\"color: #DCDCAA\">sqrt<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p><br\/>The method first retrieves the sample size; if there is only one value, it makes no sense to speak of standard error, so a domain exception is raised. In all other cases, it calls the already implemented sample standard deviation method to obtain <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-ae1901659f469e6be883797bfd30f4f8_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#115;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"8\" style=\"vertical-align: 0px;\"\/>. By dividing <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-ae1901659f469e6be883797bfd30f4f8_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#115;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"8\" style=\"vertical-align: 0px;\"\/> by the square root of n, it computes the SEM according to the canonical statistical definition and returns the result as a floating-point value. In this way, all numerical logic remains consistent with the other measures of dispersion: the function relies on well-tested methods, does not replicate existing calculations, and guarantees a very simple usage contract.   <\/p>\n\n<h2 class=\"wp-block-heading\">Mean absolute deviation (MAD)<\/h2>\n\n<p>To measure dispersion in an intuitive way, without amplifying deviations by squaring them as variance does, the <strong>mean absolute deviation<\/strong> (MAD) is used. The idea is simple: calculate the absolute distance between each observation and the arithmetic mean, then take the average of those distances. If the sample consists of the values <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-5e8319f54f72e7dac2238515c1499b27_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#120;&#95;&#49;&#44;&#32;&#120;&#95;&#50;&#44;&#32;&#92;&#100;&#111;&#116;&#115;&#44;&#32;&#120;&#95;&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"101\" style=\"vertical-align: -4px;\"\/> and their mean is <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-20ebc7ea21d727ebe3840c06a433ab09_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#98;&#97;&#114;&#123;&#120;&#125;\" title=\"Rendered by QuickLaTeX.com\" height=\"11\" width=\"10\" style=\"vertical-align: 0px;\"\/>, the mean absolute deviation is given by:  <\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-851de72c318f9c4e22aa336e66091878_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#92;&#116;&#101;&#120;&#116;&#123;&#77;&#65;&#68;&#125;&#32;&#92;&#59;&#61;&#92;&#59;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#49;&#125;&#123;&#110;&#125;&#92;&#115;&#117;&#109;&#95;&#123;&#105;&#61;&#49;&#125;&#94;&#123;&#110;&#125;&#32;&#92;&#108;&#118;&#101;&#114;&#116;&#32;&#120;&#95;&#105;&#32;&#45;&#32;&#92;&#98;&#97;&#114;&#123;&#120;&#125;&#32;&#92;&#114;&#118;&#101;&#114;&#116;\" title=\"Rendered by QuickLaTeX.com\" height=\"22\" width=\"189\" style=\"vertical-align: -6px;\"\/>.<\/p>\n\n<p>The mean absolute deviation maintains the same units of measurement as the data, is less sensitive to outliers than the standard deviation, and offers an immediate interpretation: it indicates by how many units, on average, each value deviates from the center of the distribution.<\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Calculates the mean absolute deviation (MAD) of the dataset. * * @return float The mean absolute deviation. *\/ public function meanAbsoluteDeviation(): float { $mean = $this-&lt;encoded_tag_closed \/&gt;mean(); $sumAbs = 0.0; foreach ($this-&lt;encoded_tag_closed \/&gt;data as $v) { $sumAbs += abs($v - $mean); } return $sumAbs \/ count($this-&lt;encoded_tag_closed \/&gt;data); }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Calculates the mean absolute deviation (MAD) of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The mean absolute deviation.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">meanAbsoluteDeviation<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$mean<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #DCDCAA\">mean<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$sumAbs<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\"> as <\/span><span style=\"color: #9CDCFE\">$v<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">$sumAbs<\/span><span style=\"color: #D4D4D4\"> += <\/span><span style=\"color: #DCDCAA\">abs<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$v<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">$mean<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$sumAbs<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p><br\/>The method first retrieves the arithmetic mean of the sample using the already existing <code>mean()<\/code> function. With this information, it iterates over each observation, subtracts the mean, takes the absolute value of the deviation, and accumulates it in <code>$sumAbs<\/code>. Once the loop is complete, it divides the sum of absolute deviations by the sample size, returning the result as a floating-point number. The logic remains linear and without conditional branches because the MAD formula does not require distinctions between population and sample: division by <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> always applies.   <\/p>\n\n<h2 class=\"wp-block-heading\">Percentiles<\/h2>\n\n<p>To locate any given value along the distribution, <strong>percentiles<\/strong> are used: the <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-915a1ea9fb3b667730a2c3dbdc8f1427_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#112;&#116;&#104;\" title=\"Rendered by QuickLaTeX.com\" height=\"16\" width=\"26\" style=\"vertical-align: -4px;\"\/> percentile identifies the point below which exactly <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b4f1234e2703e8efe959dc269d478e45_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#112;&#8239;&#37;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"10\" style=\"vertical-align: -4px;\"\/> of the ordered data fall. The 50th percentile coincides with the median, the 25th and 75th form the quartiles already implemented, and in general, knowing multiple percentiles allows for a very detailed description of the distribution\u2019s shape. Since the sample is finite, the percentile position rarely corresponds to an exact integer index: interpolation between adjacent elements is therefore required. A widely adopted convention (Excel and NumPy \u201clinear\u201d method) consists in calculating:   <\/p>\n\n<p><img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-abfa90ac6a2818ca37cc2160c0eda4d0_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#114;&#32;&#61;&#32;&#92;&#102;&#114;&#97;&#99;&#123;&#112;&#125;&#123;&#49;&#48;&#48;&#125;&#92;&#44;&#40;&#110;&#45;&#49;&#41;\" title=\"Rendered by QuickLaTeX.com\" height=\"20\" width=\"114\" style=\"vertical-align: -6px;\"\/><\/p>\n\n<p>where <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-b170995d512c659d8668b4e42e1fef6b_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#110;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"11\" style=\"vertical-align: 0px;\"\/> is the sample size: if r falls between indices <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-3422b6bb5c160593658b7c39425d9880_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#107;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"9\" style=\"vertical-align: 0px;\"\/> and <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-1e22674f5099474b9902f53541dfc8dc_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#107;&#43;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"14\" width=\"39\" style=\"vertical-align: -2px;\"\/>, the percentile is the linear combination of the two values, weighted by the fractional part of <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-c409433a9e2dfcdb83360a974d243f18_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#114;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"8\" style=\"vertical-align: 0px;\"\/>.<\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Returns the p-th percentile of the dataset (linear interpolation). * * @param float $p Percentile in the closed range [0, 100]. * @throws \\DomainException If $p is outside 0\u2013100. * @return float The requested percentile. *\/ public function percentile(float $p): float { if ($p &lt;encoded_tag_open \/&gt; 0.0 || $p &lt;encoded_tag_closed \/&gt; 100.0) { throw new \\DomainException('Percentile must be between 0 and 100.'); } $sorted = $this-&lt;encoded_tag_closed \/&gt;data; sort($sorted, SORT_NUMERIC); $n = count($sorted); \/\/ Edge cases: 0th and 100th percentile if ($p === 0.0) { return (float) $sorted[0]; } if ($p === 100.0) { return (float) $sorted[$n - 1]; } \/\/ Linear-interpolated rank $rank = ($p \/ 100.0) * ($n - 1); $lowerIndex = (int) floor($rank); $upperIndex = (int) ceil($rank); $weightUpper = $rank - $lowerIndex; \/\/ If rank is an integer, no interpolation is needed if ($lowerIndex === $upperIndex) { return (float) $sorted[$lowerIndex]; } $lowerValue = $sorted[$lowerIndex]; $upperValue = $sorted[$upperIndex]; return (1.0 - $weightUpper) * $lowerValue + $weightUpper * $upperValue; }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Returns the p-th percentile of the dataset (linear interpolation).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@param<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> $p Percentile in the closed range [0, 100].<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@throws<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #6A9955\"> If $p is outside 0\u2013100.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The requested percentile.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">percentile<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">$p<\/span><span style=\"color: #D4D4D4\">): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$p<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\"> || <\/span><span style=\"color: #9CDCFE\">$p<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">100.0<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">throw<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">\\DomainException<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">'Percentile must be between 0 and 100.'<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">sort<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">, SORT_NUMERIC);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #DCDCAA\">count<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Edge cases: 0th and 100th percentile<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$p<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">0.0<\/span><span style=\"color: #D4D4D4\">)   { <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">]; }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$p<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #B5CEA8\">100.0<\/span><span style=\"color: #D4D4D4\">) { <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">]; }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Linear-interpolated rank<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$rank<\/span><span style=\"color: #D4D4D4\">        = (<\/span><span style=\"color: #9CDCFE\">$p<\/span><span style=\"color: #D4D4D4\"> \/ <\/span><span style=\"color: #B5CEA8\">100.0<\/span><span style=\"color: #D4D4D4\">) * (<\/span><span style=\"color: #9CDCFE\">$n<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$lowerIndex<\/span><span style=\"color: #D4D4D4\">  = (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #DCDCAA\">floor<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$rank<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$upperIndex<\/span><span style=\"color: #D4D4D4\">  = (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #DCDCAA\">ceil<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">$rank<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$weightUpper<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$rank<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">$lowerIndex<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ If rank is an integer, no interpolation is needed<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">$lowerIndex<\/span><span style=\"color: #D4D4D4\"> === <\/span><span style=\"color: #9CDCFE\">$upperIndex<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$lowerIndex<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$lowerValue<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$lowerIndex<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">$upperValue<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">$sorted<\/span><span style=\"color: #D4D4D4\">[<\/span><span style=\"color: #9CDCFE\">$upperIndex<\/span><span style=\"color: #D4D4D4\">];<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">1.0<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">$weightUpper<\/span><span style=\"color: #D4D4D4\">) * <\/span><span style=\"color: #9CDCFE\">$lowerValue<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">$weightUpper<\/span><span style=\"color: #D4D4D4\"> * <\/span><span style=\"color: #9CDCFE\">$upperValue<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p><br\/>The method first validates that the requested percentile lies between 0 and 100 inclusive, thus ensuring consistency with the statistical definition. It then creates a sorted copy of the data, since any percentile localization requires a monotonically increasing vector. The boundary cases 0 and 100 are handled explicitly by returning the minimum and maximum of the sample, respectively. For all other values, the real rank <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-c409433a9e2dfcdb83360a974d243f18_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#114;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"8\" style=\"vertical-align: 0px;\"\/> is calculated, which may fall between two integer indices; the lower and upper indices define the interval containing the fractional position. If <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-c409433a9e2dfcdb83360a974d243f18_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#114;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"8\" style=\"vertical-align: 0px;\"\/> is already an integer, no interpolation is needed and the method returns the corresponding element directly. Otherwise, the lower and upper values are linearly combined using a weight equal to the decimal part of <img wpfc-lazyload-disable=\"true\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/renor.it\/wp-content\/ql-cache\/quicklatex.com-c409433a9e2dfcdb83360a974d243f18_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#114;\" title=\"Rendered by QuickLaTeX.com\" height=\"8\" width=\"8\" style=\"vertical-align: 0px;\"\/>, yielding a continuous result that flows smoothly between the elements of the sample.     <\/p>\n\n<h2 class=\"wp-block-heading\">Minimum and Maximum<\/h2>\n\n<p><br\/>To complete the overview of descriptive measures, it is useful to be able to quickly retrieve the lower and upper extremes of the distribution. The <strong>minimum value<\/strong> indicates the smallest observation recorded in the sample; <strong>the maximum <\/strong>marks the largest. These two quantities, although extremely simple, are essential both for providing context to the data (knowing where the observed interval begins and ends) and as components of other statistics, such as the range you have already implemented. Since the dataset is entirely in memory, finding the minimum and maximum requires only a single linear scan, and the computational cost is negligible.   <\/p>\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/** * Returns the minimum value of the dataset. * * @return float The smallest observation. *\/ public function minValue(): float { return (float) min($this-&lt;encoded_tag_closed \/&gt;data); } \/** * Returns the maximum value of the dataset. * * @return float The largest observation. *\/ public function maxValue(): float { return (float) max($this-&lt;encoded_tag_closed \/&gt;data); }\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Returns the minimum value of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The smallest observation.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">minValue<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #DCDCAA\">min<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"\/>\n<span class=\"line\"><span style=\"color: #6A9955\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * Returns the maximum value of the dataset.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> * <\/span><span style=\"color: #569CD6\">@return<\/span><span style=\"color: #6A9955\"> <\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #6A9955\"> The largest observation.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">public<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">function<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">maxValue<\/span><span style=\"color: #D4D4D4\">(): <\/span><span style=\"color: #569CD6\">float<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">float<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #DCDCAA\">max<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">$this<\/span><span style=\"color: #D4D4D4\">-&gt;<\/span><span style=\"color: #9CDCFE\">data<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n<p><br\/>The PHP functions min() and max() scan the array only once; the cast ensures that the returned type is float, consistent with the rest of the API.<\/p>\n\n<h2 class=\"wp-block-heading\">Conclusions<\/h2>\n\n<p>With this final method, we have completed our <code>DescriptiveStats<\/code> class, which now encapsulates in a single component the most important tools of descriptive statistics: from measures of central tendency (arithmetic mean, median, mode, percentiles) to measures of dispersion (range, variance, standard deviation, IQR, MAD), including indicators of robustness (trimmed mean) and uncertainty (standard error).<br\/>Each function is self-contained, strongly typed, and supported by automated PHPUnit tests, which we have not included here so as not to further lengthen an article already rich in content.  <\/p>\n\n<p>Thanks to this library, a PHP project can quickly analyze small datasets without external dependencies and without having to use artificial intelligence just to compute a \u201cmode\u201d, integrate statistical calculations into reports, dashboards, or APIs, and extend the class with additional indicators by leveraging a clear and consistent architecture. <\/p>\n\n<p>In the next article, we will see how to transform the code into a Composer package: we will create the final structure of the repository, review how to modify the <code>composer.json<\/code> file, configure CI to run the tests, and publish the library on Packagist, making it installable with a simple:<\/p>\n\n<p><code>composer require thesimon82\/descriptive-statistics<\/code><\/p>\n\n<p>In this way, you will be able to distribute your open-source solution, receive contributions from the community, and reuse it in any project with maximum simplicity.<\/p>\n\n<p>[starbox]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the world of software development, data analysis is becoming increasingly central. With the advent of artificial intelligence in the consumer market, many now use it to analyze statistical data as well. However, in many cases, the use of this technology is not required and is actually less efficient than a solid algorithm designed to [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":486,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_writerflow_disable_suggestions":false,"footnotes":""},"categories":[1977],"tags":[1406,1407,1397,1408,1409,1410,1411,1412,1413,1400,1414,1391,1415,1416,1417,1418,1419,1420],"class_list":["post-668","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-sviluppo-software-programmazione","tag-applied-mathematics","tag-arithmetic-mean","tag-composer-en","tag-data-analysis","tag-descriptive-statistics","tag-iqr-en","tag-mean-absolute-deviation","tag-median","tag-mode","tag-packagist-en","tag-percentiles","tag-php-en","tag-php-library-en-2","tag-php-tutorial","tag-programming","tag-standard-deviation","tag-standard-error","tag-variance"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.4 (Yoast SEO v27.6) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>A Descriptive Statistics Class in PHP | RENOR &amp; Partners S.r.l.<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A Descriptive Statistics Class in PHP\" \/>\n<meta property=\"og:description\" content=\"In the world of software development, data analysis is becoming increasingly central. With the advent of artificial intelligence in the consumer market, many now use it to analyze statistical data as well. However, in many cases, the use of this technology is not required and is actually less efficient than a solid algorithm designed to [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/\" \/>\n<meta property=\"og:site_name\" content=\"RENOR &amp; Partners S.r.l.\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/renorsrl\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/simone.renzi.3954\/\" \/>\n<meta property=\"article:published_time\" content=\"2025-05-12T19:06:41+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-12-20T14:53:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/renor.it\/wp-content\/uploads\/2025\/05\/statistica-descrittiva.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"1536\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Simone Renzi\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Simone Renzi\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"28 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/\"},\"author\":{\"name\":\"Simone Renzi\",\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/#\\\/schema\\\/person\\\/21343be04e5983a87f3a9a6182cf8795\"},\"headline\":\"A Descriptive Statistics Class in PHP\",\"datePublished\":\"2025-05-12T19:06:41+00:00\",\"dateModified\":\"2025-12-20T14:53:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/\"},\"wordCount\":4203,\"publisher\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/renor.it\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/statistica-descrittiva.webp\",\"keywords\":[\"applied mathematics\",\"arithmetic mean\",\"Composer\",\"data analysis\",\"descriptive statistics\",\"IQR\",\"mean absolute deviation\",\"median\",\"mode\",\"Packagist\",\"percentiles\",\"php\",\"PHP library\",\"PHP tutorial\",\"programming\",\"standard deviation\",\"standard error\",\"variance\"],\"articleSection\":[\"Sviluppo Software &amp; Programmazione\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/\",\"url\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/\",\"name\":\"A Descriptive Statistics Class in PHP | RENOR &amp; Partners S.r.l.\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/renor.it\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/statistica-descrittiva.webp\",\"datePublished\":\"2025-05-12T19:06:41+00:00\",\"dateModified\":\"2025-12-20T14:53:57+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/#primaryimage\",\"url\":\"https:\\\/\\\/renor.it\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/statistica-descrittiva.webp\",\"contentUrl\":\"https:\\\/\\\/renor.it\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/statistica-descrittiva.webp\",\"width\":1536,\"height\":1024,\"caption\":\"Figura 1 \u2013 Lavagna che riassume le principali formule di statistica descrittiva implementate nella classe DescriptiveStats (\u03bc, x\u0304\u2098\u2091d, \u03c3\u00b2, IQR, SEM, MAD) scritte a mano in stile gesso.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/sviluppo-software-programmazione\\\/a-descriptive-statistics-class-in-php\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/renor.it\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\",\"item\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Software Development &amp; Programming\",\"item\":\"https:\\\/\\\/renor.it\\\/en\\\/blog\\\/software-development-programming\\\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"A Descriptive Statistics Class in PHP\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/renor.it\\\/en\\\/\",\"name\":\"RENOR & Partners S.r.l.\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/#organization\"},\"alternateName\":\"RENOR & Partners S.r.l.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/renor.it\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/#organization\",\"name\":\"RENOR & Partners S.r.l.\",\"url\":\"https:\\\/\\\/renor.it\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/renor.it\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/logo-new-1.webp\",\"contentUrl\":\"https:\\\/\\\/renor.it\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/logo-new-1.webp\",\"width\":432,\"height\":146,\"caption\":\"RENOR & Partners S.r.l.\"},\"image\":{\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/renorsrl\",\"https:\\\/\\\/www.instagram.com\\\/renorpartners\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/renor-partners\\\/posts\\\/?feedView=all\"],\"description\":\"RENOR & Partners Srl \u00e8 una societ\u00e0 di consulenza tecnologica e ingegneristica specializzata in sviluppo software, cloud computing, integrazione di sistemi, intelligenza artificiale applicata e progettazione elettronica. L\u2019azienda supporta imprese e pubbliche amministrazioni nella realizzazione di soluzioni digitali affidabili, scalabili e orientate all\u2019efficienza, con un approccio pragmatico basato su competenze tecniche, progettazione su misura e innovazione concreta.\",\"email\":\"info@renor.it\",\"telephone\":\"3791489430\",\"legalName\":\"RENOR AND PARTNERS S.r.l.\",\"foundingDate\":\"2022-06-21\",\"vatID\":\"16768411007\",\"taxID\":\"16768411007\",\"numberOfEmployees\":{\"@type\":\"QuantitativeValue\",\"minValue\":\"1\",\"maxValue\":\"10\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/renor.it\\\/en\\\/#\\\/schema\\\/person\\\/21343be04e5983a87f3a9a6182cf8795\",\"name\":\"Simone Renzi\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/54f81b51be6bda6d63a06a1cd6563d9b0d5778d7af4f0bda4e246fc3e5737e2e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/54f81b51be6bda6d63a06a1cd6563d9b0d5778d7af4f0bda4e246fc3e5737e2e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/54f81b51be6bda6d63a06a1cd6563d9b0d5778d7af4f0bda4e246fc3e5737e2e?s=96&d=mm&r=g\",\"caption\":\"Simone Renzi\"},\"description\":\"Senior full-stack web engineer with over 20 years of experience in cloud architectures, AI, and SaaS solutions; member of Mensa Italia. Creator of platforms such as HR24.ai and Paghe.ai, he oversaw the web development of FNS, a neural network simulator cited in Scientific Reports (Nature Portfolio), and has collaborated on research projects with INFN \u2013 Laboratori Nazionali di Frascati, Universit\u00e0 di Roma \u201cTor Vergata\u201d, Universidad Complutense, Universidad Polit\u00e9cnica and Centro de Tecnolog\u00eda Biom\u00e9dica in Madrid. A classical pianist, he combines musical creativity and technological rigor in every project.\",\"sameAs\":[\"https:\\\/\\\/renor.it\",\"https:\\\/\\\/www.facebook.com\\\/simone.renzi.3954\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/simone-renzi\"],\"url\":\"https:\\\/\\\/renor.it\\\/en\\\/author\\\/thesimon\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"A Descriptive Statistics Class in PHP | RENOR &amp; Partners S.r.l.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/","og_locale":"en_US","og_type":"article","og_title":"A Descriptive Statistics Class in PHP","og_description":"In the world of software development, data analysis is becoming increasingly central. With the advent of artificial intelligence in the consumer market, many now use it to analyze statistical data as well. However, in many cases, the use of this technology is not required and is actually less efficient than a solid algorithm designed to [&hellip;]","og_url":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/","og_site_name":"RENOR &amp; Partners S.r.l.","article_publisher":"https:\/\/www.facebook.com\/renorsrl","article_author":"https:\/\/www.facebook.com\/simone.renzi.3954\/","article_published_time":"2025-05-12T19:06:41+00:00","article_modified_time":"2025-12-20T14:53:57+00:00","og_image":[{"width":1536,"height":1024,"url":"https:\/\/renor.it\/wp-content\/uploads\/2025\/05\/statistica-descrittiva.webp","type":"image\/webp"}],"author":"Simone Renzi","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Simone Renzi","Est. reading time":"28 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/#article","isPartOf":{"@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/"},"author":{"name":"Simone Renzi","@id":"https:\/\/renor.it\/en\/#\/schema\/person\/21343be04e5983a87f3a9a6182cf8795"},"headline":"A Descriptive Statistics Class in PHP","datePublished":"2025-05-12T19:06:41+00:00","dateModified":"2025-12-20T14:53:57+00:00","mainEntityOfPage":{"@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/"},"wordCount":4203,"publisher":{"@id":"https:\/\/renor.it\/en\/#organization"},"image":{"@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/#primaryimage"},"thumbnailUrl":"https:\/\/renor.it\/wp-content\/uploads\/2025\/05\/statistica-descrittiva.webp","keywords":["applied mathematics","arithmetic mean","Composer","data analysis","descriptive statistics","IQR","mean absolute deviation","median","mode","Packagist","percentiles","php","PHP library","PHP tutorial","programming","standard deviation","standard error","variance"],"articleSection":["Sviluppo Software &amp; Programmazione"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/","url":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/","name":"A Descriptive Statistics Class in PHP | RENOR &amp; Partners S.r.l.","isPartOf":{"@id":"https:\/\/renor.it\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/#primaryimage"},"image":{"@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/#primaryimage"},"thumbnailUrl":"https:\/\/renor.it\/wp-content\/uploads\/2025\/05\/statistica-descrittiva.webp","datePublished":"2025-05-12T19:06:41+00:00","dateModified":"2025-12-20T14:53:57+00:00","breadcrumb":{"@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/#primaryimage","url":"https:\/\/renor.it\/wp-content\/uploads\/2025\/05\/statistica-descrittiva.webp","contentUrl":"https:\/\/renor.it\/wp-content\/uploads\/2025\/05\/statistica-descrittiva.webp","width":1536,"height":1024,"caption":"Figura 1 \u2013 Lavagna che riassume le principali formule di statistica descrittiva implementate nella classe DescriptiveStats (\u03bc, x\u0304\u2098\u2091d, \u03c3\u00b2, IQR, SEM, MAD) scritte a mano in stile gesso."},{"@type":"BreadcrumbList","@id":"https:\/\/renor.it\/en\/blog\/sviluppo-software-programmazione\/a-descriptive-statistics-class-in-php\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/renor.it\/en\/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https:\/\/renor.it\/en\/blog\/"},{"@type":"ListItem","position":3,"name":"Software Development &amp; Programming","item":"https:\/\/renor.it\/en\/blog\/software-development-programming\/"},{"@type":"ListItem","position":4,"name":"A Descriptive Statistics Class in PHP"}]},{"@type":"WebSite","@id":"https:\/\/renor.it\/en\/#website","url":"https:\/\/renor.it\/en\/","name":"RENOR & Partners S.r.l.","description":"","publisher":{"@id":"https:\/\/renor.it\/en\/#organization"},"alternateName":"RENOR & Partners S.r.l.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/renor.it\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/renor.it\/en\/#organization","name":"RENOR & Partners S.r.l.","url":"https:\/\/renor.it\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/renor.it\/en\/#\/schema\/logo\/image\/","url":"https:\/\/renor.it\/wp-content\/uploads\/2025\/12\/logo-new-1.webp","contentUrl":"https:\/\/renor.it\/wp-content\/uploads\/2025\/12\/logo-new-1.webp","width":432,"height":146,"caption":"RENOR & Partners S.r.l."},"image":{"@id":"https:\/\/renor.it\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/renorsrl","https:\/\/www.instagram.com\/renorpartners\/","https:\/\/www.linkedin.com\/company\/renor-partners\/posts\/?feedView=all"],"description":"RENOR & Partners Srl \u00e8 una societ\u00e0 di consulenza tecnologica e ingegneristica specializzata in sviluppo software, cloud computing, integrazione di sistemi, intelligenza artificiale applicata e progettazione elettronica. L\u2019azienda supporta imprese e pubbliche amministrazioni nella realizzazione di soluzioni digitali affidabili, scalabili e orientate all\u2019efficienza, con un approccio pragmatico basato su competenze tecniche, progettazione su misura e innovazione concreta.","email":"info@renor.it","telephone":"3791489430","legalName":"RENOR AND PARTNERS S.r.l.","foundingDate":"2022-06-21","vatID":"16768411007","taxID":"16768411007","numberOfEmployees":{"@type":"QuantitativeValue","minValue":"1","maxValue":"10"}},{"@type":"Person","@id":"https:\/\/renor.it\/en\/#\/schema\/person\/21343be04e5983a87f3a9a6182cf8795","name":"Simone Renzi","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/54f81b51be6bda6d63a06a1cd6563d9b0d5778d7af4f0bda4e246fc3e5737e2e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/54f81b51be6bda6d63a06a1cd6563d9b0d5778d7af4f0bda4e246fc3e5737e2e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/54f81b51be6bda6d63a06a1cd6563d9b0d5778d7af4f0bda4e246fc3e5737e2e?s=96&d=mm&r=g","caption":"Simone Renzi"},"description":"Senior full-stack web engineer with over 20 years of experience in cloud architectures, AI, and SaaS solutions; member of Mensa Italia. Creator of platforms such as HR24.ai and Paghe.ai, he oversaw the web development of FNS, a neural network simulator cited in Scientific Reports (Nature Portfolio), and has collaborated on research projects with INFN \u2013 Laboratori Nazionali di Frascati, Universit\u00e0 di Roma \u201cTor Vergata\u201d, Universidad Complutense, Universidad Polit\u00e9cnica and Centro de Tecnolog\u00eda Biom\u00e9dica in Madrid. A classical pianist, he combines musical creativity and technological rigor in every project.","sameAs":["https:\/\/renor.it","https:\/\/www.facebook.com\/simone.renzi.3954\/","https:\/\/www.linkedin.com\/in\/simone-renzi"],"url":"https:\/\/renor.it\/en\/author\/thesimon\/"}]}},"_links":{"self":[{"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/posts\/668","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/comments?post=668"}],"version-history":[{"count":0,"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/posts\/668\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/media\/486"}],"wp:attachment":[{"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/media?parent=668"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/categories?post=668"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/renor.it\/en\/wp-json\/wp\/v2\/tags?post=668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}