2

Density Chart

PreviousNext

2D kernel density estimation with contour visualization.

20406080100X Value102030405060708090Y Value
"use client"

import { DensityChart } from "@/components/ui/charts/scientific/density-chart"

// Generate clustered 2D data
function generateClusteredData(): { x: number; y: number }[] {
  const data: { x: number; y: number }[] = []

  // Cluster 1 - bottom left
  for (let i = 0; i < 40; i++) {
    data.push({
      x: 20 + Math.random() * 25 + (Math.random() - 0.5) * 10,
      y: 25 + Math.random() * 20 + (Math.random() - 0.5) * 10,
    })
  }

  // Cluster 2 - top right
  for (let i = 0; i < 35; i++) {
    data.push({
      x: 60 + Math.random() * 25 + (Math.random() - 0.5) * 10,
      y: 55 + Math.random() * 25 + (Math.random() - 0.5) * 10,
    })
  }

  // Cluster 3 - middle
  for (let i = 0; i < 25; i++) {
    data.push({
      x: 45 + Math.random() * 15 + (Math.random() - 0.5) * 8,
      y: 40 + Math.random() * 15 + (Math.random() - 0.5) * 8,
    })
  }

  return data
}

const clusterData = generateClusteredData()

export function DensityChartDemo() {
  return (
    <div className="mx-auto w-full max-w-lg">
      <DensityChart
        data={clusterData}
        showPoints
        showContours
        bandwidth={18}
        thresholds={8}
        xAxisLabel="X Value"
        yAxisLabel="Y Value"
      />
    </div>
  )
}

About

The Density Chart (2D Density Plot) visualizes the distribution of points in two dimensions using kernel density estimation (KDE). Contours show areas of equal density, making it easy to identify clusters and patterns in scatter data.

Installation

pnpm dlx shadcn@latest add https://ui.simplifying.ai/r/density-chart.json

Usage

import { DensityChart } from "@/components/ui/charts"
 
const data = [
  { x: 10, y: 20 },
  { x: 15, y: 25 },
  { x: 12, y: 22 },
  // ... more points
]
 
export function Example() {
  return <DensityChart data={data} showPoints showContours />
}

Variants

Contours Only

Hide individual points to focus on density patterns.

-20020406080100120Feature X020406080100Feature Y
"use client"

import { interpolateViridis } from "d3-scale-chromatic"

import { DensityChart } from "@/components/ui/charts/scientific/density-chart"

// Generate normally distributed 2D data
function generateNormalData(): { x: number; y: number }[] {
  const data: { x: number; y: number }[] = []

  // Box-Muller transform for normal distribution
  const normalRandom = (mean: number, std: number) => {
    const u = 1 - Math.random()
    const v = Math.random()
    const z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v)
    return z * std + mean
  }

  for (let i = 0; i < 200; i++) {
    data.push({
      x: normalRandom(50, 15),
      y: normalRandom(50, 15),
    })
  }

  return data
}

const normalData = generateNormalData()

export function DensityChartContoursOnly() {
  return (
    <div className="mx-auto w-full max-w-lg">
      <DensityChart
        data={normalData}
        showPoints={false}
        showContours
        bandwidth={25}
        thresholds={12}
        colorScale={interpolateViridis}
        xAxisLabel="Feature X"
        yAxisLabel="Feature Y"
      />
    </div>
  )
}

API Reference

PropTypeDefaultDescription
dataDensityDataPoint[]requiredArray of x, y points
showPointsbooleantrueShow individual data points
showContoursbooleantrueShow density contours
bandwidthnumber20KDE bandwidth (smoothing)
thresholdsnumber10Number of contour levels
pointRadiusnumber3Radius of data points
pointColorstring"#1e40af"Color for data points
colorScalefunctioninterpolateBluesContour color scale
xAxisLabelstringundefinedX-axis label
yAxisLabelstringundefinedY-axis label

Notes

  • The density chart uses kernel density estimation (KDE) to smooth point distributions
  • Increase bandwidth for smoother, more generalized density patterns
  • Decrease bandwidth to capture finer details in the density distribution
  • The thresholds prop controls how many contour levels are shown (more levels = more detail)
  • For large datasets (1000+ points), consider hiding individual points with showPoints={false} for better performance
  • Works best with datasets that have at least 20-30 points for meaningful density estimation