Skip to content
← Back to Functions
Code

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;
}