PCA Projection Viz
A square SVG plane that visualizes principal component analysis on a 2D point cloud. The cloud's centroid is computed, the two-by-two covariance matrix is eigen-decomposed analytically, and the principal axes are drawn from the centroid — each scaled by the square root of its eigenvalue, so the dominant direction is visually loudest. With showProjections, perpendicular drops from each point onto PC1 reveal how PCA flattens the cloud to one dimension.
Principal component analysis on 20 points. PC1 variance fraction 0.91, PC2 variance fraction 0.09.
PC1 0.91PC2 0.09
Customize
Data
elongated
Axes
both
Installation
npx shadcn@latest add https://craftbits.dev/r/pca-projection-viz.jsonUsage
import { PCAProjectionViz } from "@craft-bits/core";
<PCAProjectionViz
points={[
{ x: 1.2, y: 0.5 },
{ x: 2.4, y: 1.1 },
{ x: -1.0, y: -0.4 },
]}
/>Show only the dominant axis with each point projected onto it:
<PCAProjectionViz
points={cloud}
pcMode="pc1"
showProjections
/>Hide the axes entirely for a plain scatter:
<PCAProjectionViz points={cloud} showAxes={false} />Understanding the component
- Centroid first. The cloud mean is computed once and everything else is centered there — the axes are drawn from the centroid, the covariance is computed about it, and the auto-fit viewport is centered on it.
- Analytical two-by-two eigen-decomposition. The covariance matrix is two-by-two, so the eigenvalues are the closed-form roots of the characteristic polynomial. The eigenvector for the larger eigenvalue is derived from the singular system with a numerically safe branch when the off-diagonal entry is near zero. PC2 is the 90° rotation of PC1.
- Axes scaled by the square root of lambda. The arrow length is
axisScaletimes the standard deviation along that direction. Doubling the spread doubles the arrow. - Two tones. PC1 draws in
var(--cb-accent)with the bold edge token; PC2 draws invar(--cb-fg-muted)with the normal edge token — so the dominant axis is visually loudest. - Optional projection drops. When
showProjectionsis on, a dotted segment connects each point to its foot on the PC1 axis. The foot is the standard scalar-projection formula applied to the centered points. - Auto-fit viewport. The SVG viewport is centered on the centroid and sized to fit both the cloud extents and the axis arrows, with a 15 percent margin. No
rangeprop — the viewport adapts so any cloud shape looks right. - Variance fractions below. PC1 / PC2 contribution to total variance is shown as the eigenvalue ratio beneath the plot, in tabular numerals.
- Spring transitions. Axes, projection lines, and the centroid follow with
SPRINGS.smooth.prefers-reduced-motion: reducecollapses every spring toduration: 0.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
points | readonly PCAPoint[] | required | 2D points to analyze. |
showAxes | boolean | true | Render the PC1 / PC2 axes from the centroid. |
showProjections | boolean | false | Drop a perpendicular from each point onto PC1. |
pcMode | "pc1" | "pc2" | "both" | "both" | Which principal axes to draw. |
axisScale | number | 2 | Multiplier for arrow length. |
size | number | 320 | SVG side length in pixels (the plane is square). |
transition | Transition | SPRINGS.smooth | Spring for axis / projection transitions. |
className | string | — | Merged onto the root <div> via cn(). |
The PCAPoint shape:
| Field | Type | Description |
|---|---|---|
x | number | x coordinate in math space. |
y | number | y coordinate in math space. |
Accessibility
- The SVG is
role="figure"with anaria-labelledbyheading also rendered as a visually hiddenaria-live="polite"summary — screen readers hear the variance fractions wheneverpointschange. - The visualization is read-only — no interactive handles to enumerate.
- Variance-fraction readouts use tabular numerals so the columns stay aligned as values change.
- Animation respects
prefers-reduced-motion: reduce— every spring collapses to an instant swap.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/viz/PCAProjectionViz.tsx). The source paired the visualization with a draggable rotating-axis explorer, Explore / Predict / Challenge mode strip, narration heuristics, history-undo state machine, and preset bookmarks. The library extract is the pure visualization primitive — a 2D cloud, its analytically computed principal axes, and an optional projection drop. Mode strips, score dots, and narration belong in the consuming lesson, not the primitive.