Skip to content
← Back to Functions
Code

Histogram Bucket Builder

Groups numeric values into histogram buckets with counts and percentages.

Function signature

ogBuildHistogramBuckets(values = array(), options = array())

Categories

  • Analytics and Reports

Parameters

valuesNumeric values or rows with a value key.optionsOptions: bucket_count or buckets. Recognized keys: `bucket_count`.

Return value

Short public-safe status message.

  • total
  • buckets

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, policy arrays, URLs, signatures, 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.
 */

/**
 * Groups numeric values into histogram buckets with counts and percentages.
 *
 * @param array $values Numeric values or rows with a value key.
 * @param array $options Options: bucket_count or buckets.
 * @return array Histogram bucket report.
 */
function ogBuildHistogramBuckets($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();
	}

	$numbers = array();
	foreach ($values as $value) {
		if (is_array($value) && isset($value['value']) && is_numeric($value['value'])) {
			$numbers[] = (float)$value['value'];
		} elseif (is_numeric($value)) {
			$numbers[] = (float)$value;
		}
	}

	if (empty($numbers)) {
		$result['message'] = 'No numeric values were supplied.';
		return $result;
	}

	$minimum = min($numbers);
	$maximum = max($numbers);
	$bucket_count = 10;
	if (!empty($options['bucket_count'])) {
		$bucket_count = (int)$options['bucket_count'];
	}
	if ($bucket_count < 1) {
		$bucket_count = 10;
	}

	$width = ($maximum - $minimum) / $bucket_count;
	if ($width <= 0) {
		$width = 1;
	}

	$buckets = array();
	for ($i = 0; $i < $bucket_count; $i++) {
		$start = $minimum + ($i * $width);
		$end = $start + $width;
		$buckets[$i] = array('start' => $start, 'end' => $end, 'count' => 0, 'percent' => 0);
	}

	foreach ($numbers as $number) {
		$index = (int)floor(($number - $minimum) / $width);
		if ($index < 0) {
			$index = 0;
		}
		if ($index >= $bucket_count) {
			$index = $bucket_count - 1;
		}
		$buckets[$index]['count']++;
	}

	$total = count($numbers);
	foreach ($buckets as $index => $bucket) {
		$buckets[$index]['percent'] = ($bucket['count'] / $total) * 100;
	}

	$result['success'] = true;
	$result['message'] = 'Histogram buckets built.';
	$result['data'] = array('total' => $total, 'buckets' => $buckets);

	return $result;
}