kernelDensityEstimation function

KernelDensityResult kernelDensityEstimation(
  1. List<double> data, {
  2. double? bandwidth,
  3. KernelType kernel = KernelType.gaussian,
  4. int nPoints = 100,
  5. List<double>? range,
})

Computes kernel density estimation for a set of data points.

data is the input data. bandwidth is the kernel bandwidth (smoothing parameter). If not provided, Silverman's rule of thumb is used. kernel is the type of kernel to use (default: gaussian). nPoints is the number of points to evaluate the density at. range is the optional range min, max for evaluation.

Implementation

KernelDensityResult kernelDensityEstimation(
  List<double> data, {
  double? bandwidth,
  KernelType kernel = KernelType.gaussian,
  int nPoints = 100,
  List<double>? range,
}) {
  if (data.isEmpty) {
    return KernelDensityResult(x: [], density: []);
  }

  // Calculate bandwidth using Silverman's rule if not provided
  final h = bandwidth ?? _silvermanBandwidth(data);

  // Determine evaluation range
  double minX, maxX;
  if (range != null && range.length >= 2) {
    minX = range[0];
    maxX = range[1];
  } else {
    minX = data.reduce(math.min) - 3 * h;
    maxX = data.reduce(math.max) + 3 * h;
  }

  // Generate evaluation points
  final xValues = List<double>.generate(
    nPoints,
    (i) => minX + (maxX - minX) * i / (nPoints - 1),
  );

  // Select kernel function
  double Function(double) kernelFn;
  switch (kernel) {
    case KernelType.gaussian:
      kernelFn = _gaussianKernel;
      break;
    case KernelType.epanechnikov:
      kernelFn = _epanechnikovKernel;
      break;
    case KernelType.triangular:
      kernelFn = _triangularKernel;
      break;
    case KernelType.uniform:
      kernelFn = _uniformKernel;
      break;
  }

  // Estimate density at each point
  final n = data.length;
  final density = List<double>.filled(nPoints, 0);

  for (int i = 0; i < nPoints; i++) {
    double sum = 0;
    for (int j = 0; j < n; j++) {
      sum += kernelFn((xValues[i] - data[j]) / h);
    }
    density[i] = sum / (n * h);
  }

  return KernelDensityResult(x: xValues, density: density);
}