Percentile Summary Builder
Calculates median, quartiles, and selected percentiles from numeric values.
Function signature
ogBuildPercentileSummary(values = array(), options = array())
Categories
- Analytics and Reports
Parameters
valuesNumeric values.optionsOptional key: percentiles. Recognized keys: `percentiles`.Return value
Short public-safe status message.
- count
- minimum
- maximum
- median
- percentiles
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets and internal paths out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Calculates median, quartiles, and selected percentiles from numeric values.
*
* @param array $values Numeric values.
* @param array $options Optional key: percentiles.
* @return array Percentile summary with sorted count and requested percentile values.
*/
function ogBuildPercentileSummary($values = array(), $options = array()) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
if (!is_array($values)) {
$result['message'] = 'Values must be an array.';
return $result;
}
if (!is_array($options)) {
$options = array();
}
$numeric_values = array();
foreach ($values as $value) {
if (is_numeric($value)) {
$numeric_values[] = (float)$value;
}
}
if (empty($numeric_values)) {
$result['message'] = 'No numeric values were supplied.';
return $result;
}
sort($numeric_values, SORT_NUMERIC);
$count = count($numeric_values);
$requested = array(25, 50, 75, 90, 95, 99);
if (!empty($options['percentiles']) && is_array($options['percentiles'])) {
$requested = $options['percentiles'];
}
$percentiles = array();
foreach ($requested as $percentile) {
$percentile = (float)$percentile;
if ($percentile < 0) {
$percentile = 0;
}
if ($percentile > 100) {
$percentile = 100;
}
$rank = ($percentile / 100) * ($count - 1);
$lower_index = (int)floor($rank);
$upper_index = (int)ceil($rank);
$weight = $rank - $lower_index;
$value = $numeric_values[$lower_index];
if ($upper_index != $lower_index) {
$value = $numeric_values[$lower_index] + (($numeric_values[$upper_index] - $numeric_values[$lower_index]) * $weight);
}
$percentiles[(string)$percentile] = $value;
}
$result['success'] = true;
$result['message'] = 'Percentile summary built.';
$result['data'] = array(
'count' => $count,
'minimum' => $numeric_values[0],
'maximum' => $numeric_values[$count - 1],
'median' => $percentiles['50'],
'percentiles' => $percentiles
);
return $result;
}