histogram<T> function

List<Bin<T>> histogram<T>({
  1. required Iterable<T> data,
  2. required num value(
    1. T
    ),
  3. int? thresholds,
  4. List<num>? domain,
})

Generates a histogram from the given values.

Implementation

List<Bin<T>> histogram<T>({
  required Iterable<T> data,
  required num Function(T) value,
  int? thresholds,
  List<num>? domain,
}) {
  final values = data.toList();
  if (values.isEmpty) return [];

  // Calculate domain
  num minValue, maxValue;
  if (domain != null && domain.length >= 2) {
    minValue = domain[0];
    maxValue = domain[1];
  } else {
    final ext = extentBy(values, value);
    if (ext == null) return [];
    minValue = ext.$1;
    maxValue = ext.$2;
  }

  // Calculate number of bins using Sturges' formula if not provided
  final binCount = thresholds ??
      math.max(1, (math.log(values.length) / math.ln2).ceil() + 1);

  // Calculate bin width
  final binWidth = (maxValue - minValue) / binCount;
  if (binWidth == 0) {
    return [
      Bin(
        x0: minValue,
        x1: maxValue,
        values: values,
      ),
    ];
  }

  // Create bins
  final bins = List.generate(
    binCount,
    (i) => Bin<T>(
      x0: minValue + i * binWidth,
      x1: minValue + (i + 1) * binWidth,
      values: <T>[],
    ),
  );

  // Distribute values into bins
  for (final item in values) {
    final v = value(item);
    if (v < minValue || v > maxValue) continue;

    int binIndex = ((v - minValue) / binWidth).floor();
    if (binIndex >= binCount) binIndex = binCount - 1;
    bins[binIndex].values.add(item);
  }

  return bins;
}