HAHS.
Back to Catalog

Cross-filter

interaction

Also known as: crossfilter, coordinated filter, multi-dimensional filter

Filter / focusEnable explorationShow relationshipShow distribution NumericalTemporalCategorical

Description

Cross-filtering is a multi-view interaction technique in which brushing or filtering in any one chart simultaneously constrains the data shown in all other charts. The defining characteristic is that each chart shows the distribution of its own dimension, filtered by the selections active in all other charts — but not by its own selection. This asymmetric filtering allows each chart to serve as both a filter control and a data display, creating a tightly coupled exploratory environment.

The technique was popularized by the Crossfilter.js library (developed by Mike Bostock and others at Square, 2012) which demonstrated that multi-dimensional filtering over hundreds of thousands of records could happen at interactive speeds in the browser. The library used sorted indices and incremental filtering to achieve sub-millisecond updates, making the tight feedback loop essential to the interaction feel achievable in JavaScript.

Cross-filtering excels at exploratory data analysis tasks where the user wants to understand how different data dimensions relate. By brushing a range on one histogram (e.g., flight delay > 30 minutes) and observing how the distributions shift in other histograms (time of day, carrier, origin airport), the user can rapidly build a mental model of the data’s multivariate structure. This makes it one of the most powerful techniques for multi-dimensional data exploration, but it requires careful engineering to maintain performance as the dataset and number of views grow.

Cross Filter — try it yourself

When to Use

  • When exploring a dataset with 3-8 numerical or categorical dimensions that might interact in interesting ways.
  • When each dimension has a natural chart type (histograms for continuous, bar charts for categorical) and the goal is to understand joint distributions.
  • In dashboard contexts where users need to answer “show me the distribution of Y for items where X is in this range.”
  • When the dataset is small-to-medium (up to a few hundred thousand rows) and real-time filtering is feasible.
  • For data auditing, anomaly detection, and quality checking workflows.

When NOT to Use

  • When there are only 1-2 dimensions — a simple dynamic query or brush suffices.
  • When the dataset is so large that real-time cross-filtering is computationally infeasible without server-side processing.
  • When the dimensions are not meaningfully independent — cross-filtering redundant dimensions wastes screen space.
  • When the audience expects a guided narrative rather than open exploration.
  • When the number of charts exceeds what the user can cognitively track (more than 8-10 simultaneous views becomes overwhelming).

How It Works

  1. Multiple charts are arranged in a dashboard layout, each showing a different dimension of the same dataset (e.g., histograms of price, rating, year; bar charts of category, region).
  2. The user brushes a range in one chart — for example, selecting years 2010–2015 on the year histogram.
  3. All other charts immediately update to show the distribution of their dimension filtered to only items within the brushed year range.
  4. The brushed chart itself does NOT re-filter its own bars — it continues to show the full distribution with the brush overlay, so the user can adjust the selection.
  5. The user can brush additional charts, adding intersection filters. Brushing carrier “Delta” on the carrier bar chart further constrains the data in all views except the carrier chart.
  6. Clearing a brush on any chart removes that dimension’s filter, and all other charts update accordingly.
  7. Summary statistics (total count, mean values) update alongside the charts.

Variations

  • Histogram cross-filter: The classic form. Each dimension gets a histogram with a 1D brush. Popularized by Crossfilter.js.
  • Chart-type heterogeneous cross-filter: Different chart types per dimension — scatterplot for two continuous variables, bar chart for categorical, timeline for temporal.
  • Server-side cross-filter: For large datasets, the filtering is computed on a server or database, with the client sending brush extents as query parameters. Libraries like Falcon and OmniSci Immerse implement this.
  • Approximate cross-filter: Uses data cubes, sampling, or approximate query processing to maintain interactive speeds on very large data.
  • Cross-filter with aggregation change: As filters narrow, the aggregation level can change (e.g., from monthly to daily bins as the time range shrinks).

Code Reference

// Conceptual cross-filter with D3 and Crossfilter.js
const cf = crossfilter(data);
const dimYear = cf.dimension(d => d.year);
const dimPrice = cf.dimension(d => d.price);
const grpYear = dimYear.group();
const grpPrice = dimPrice.group(d => Math.floor(d / 10) * 10);

// When the user brushes the year chart:
function onYearBrush([y0, y1]) {
  dimYear.filterRange([y0, y1]);
  // Price chart re-renders using grpPrice.all()
  // which now reflects only items in the year range
  renderPriceChart(grpPrice.all());
}