Skip to content

D3.js - Array API

D3’s d3-array module provides a powerful suite of functions for array manipulation and analysis. These utilities are helpful for data processing, statistical calculations, and preparing data for visualization. This chapter explores the key features of the Array API.

The d3-array module is part of the main D3.js bundle. If you are using D3 modules individually, you can install and import d3-array.

<!-- Option 1: Include the full D3 library -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<!-- Option 2: Include the standalone d3-array module -->
<!-- <script src="https://d3js.org/d3-array.v3.min.js"></script> -->
<script>
// Example usage:
// const numbers = [1, 5, 2, 8, 3];
// console.log(d3.min(numbers)); // 1
// console.log(d3.max(numbers)); // 8
</script>

These methods compute basic summary statistics for an array.

  • d3.min(array[, accessor]) − Returns the minimum value in the array using natural order. An optional accessor function can be used to derive values from array elements.
  • d3.max(array[, accessor]) − Returns the maximum value.
  • d3.extent(array[, accessor]) − Returns an array [min, max] representing the minimum and maximum values.
  • d3.sum(array[, accessor]) − Returns the sum of all values. Ignores NaN and undefined values.
  • d3.mean(array[, accessor]) − Returns the arithmetic mean (average).
  • d3.median(array[, accessor]) − Returns the median (the middle value).
  • d3.quantile(array, p[, accessor]) − Returns the p-quantile, where p is a number in [0, 1]. E.g., p=0.5 is the median.
  • d3.variance(array[, accessor]) − Returns the sample variance.
  • d3.deviation(array[, accessor]) − Returns the standard deviation (square root of variance).
const data = [20, 40, 60, 80, 100];
const objects = [{value: 10}, {value: 5}, {value: 15}];
console.log(`Min: ${d3.min(data)}`); // Min: 20
console.log(`Max: ${d3.max(data)}`); // Max: 100
console.log(`Extent: ${d3.extent(data)}`); // Extent: 20,100
console.log(`Sum: ${d3.sum(data)}`); // Sum: 300
console.log(`Mean: ${d3.mean(data)}`); // Mean: 60
console.log(`Median: ${d3.median(data)}`); // Median: 60
console.log(`Quantile (0.25): ${d3.quantile(data, 0.25)}`); // Quantile (0.25): 40
console.log(`Variance: ${d3.variance(data)}`); // Variance: 1000
console.log(`Deviation: ${d3.deviation(data)}`); // Deviation: 31.622...
// Using an accessor
console.log(`Min object value: ${d3.min(objects, d => d.value)}`); // Min object value: 5

These methods help find elements or indices within arrays.

  • d3.scan(array[, comparator]) − Performs a linear scan, returning the index of the element with the smallest value according to the comparator. Default comparator is d3.ascending.
  • d3.bisectLeft(array, x[, lo[, hi]]) − Returns the insertion point for x in array to maintain sorted order. Assumes array is sorted.
  • d3.bisectRight(array, x[, lo[, hi]]) − Similar to bisectLeft, but returns the rightmost insertion point.
  • d3.bisectCenter(array, x[, lo[, hi]]) - Returns the index of the element closest to x in a sorted array.
  • d3.ascending(a, b) − A comparator function: returns -1 if a < b, 1 if a > b, 0 if a == b, NaN otherwise.
  • d3.descending(a, b) − A comparator function for descending order.
const unsortedObjects = [{id: 'c', val: 30}, {id: 'a', val: 10}, {id: 'b', val: 20}];
const sortedNumbers = [10, 20, 30, 40, 50];
// Find index of object with minimum 'val'
const minValIndex = d3.scan(unsortedObjects, (a, b) => d3.ascending(a.val, b.val));
console.log(`Index of min val: ${minValIndex}, Object:`, unsortedObjects[minValIndex]); // Index: 1, Object: {id: 'a', val: 10}
// Bisect example (for sorted arrays)
console.log(`Bisect left for 25: ${d3.bisectLeft(sortedNumbers, 25)}`); // Bisect left for 25: 2
console.log(`Bisect right for 30: ${d3.bisectRight(sortedNumbers, 30)}`); // Bisect right for 30: 3
console.log(`Bisect center for 28: ${d3.bisectCenter(sortedNumbers, 28)}`);// Bisect center for 28: 2 (index of 30)

These methods generate new arrays from existing ones.

  • d3.cross(a, b[, reducer]) − Returns the Cartesian product of arrays a and b. An optional reducer function can transform each pair.
  • d3.merge(arrays) − Merges an array of arrays into a single array.
  • d3.pairs(array[, reducer]) − Returns an array of adjacent pairs [a, b] from the input array. An optional reducer can transform pairs.
  • d3.permute(array, order) − Returns a permutation of array according to the specified order (an array of indices). Can also permute properties of an object.
  • d3.shuffle(array[, start[, stop]]) - Randomizes the order of elements in an array in-place (Fisher-Yates shuffle). Returns the shuffled array.
  • d3.ticks(start, stop, count) − Generates approximately count uniformly-spaced, human-readable values between start and stop. Useful for axis ticks.
  • d3.tickStep(start, stop, count) - Returns the step size for d3.ticks.
  • d3.tickIncrement(start, stop, count) - Like d3.tickStep but for dates.
  • d3.range([start, ]stop[, step]) − Generates an array of numbers, similar to Python’s range. start defaults to 0, step to 1.
  • d3.zip(arrays…) − Transposes an array of arrays. For example, d3.zip([1,2], [3,4]) yields [[1,3], [2,4]].
console.log('Cross:', JSON.stringify(d3.cross([1, 2], ['a', 'b'])));
// Cross: [[1,"a"],[1,"b"],[2,"a"],[2,"b"]]
console.log('Merge:', d3.merge([[1, 2], [3, 4]]));
// Merge: [1, 2, 3, 4]
console.log('Pairs:', JSON.stringify(d3.pairs([1, 2, 3, 4])));
// Pairs: [[1,2],[2,3],[3,4]]
const obj = {name: 'D3', type: 'library'};
const order = ['type', 'name'];
console.log('Permute object:', d3.permute(obj, order));
// Permute object: ["library", "D3"]
console.log('Zip:', JSON.stringify(d3.zip([1, 2], ['a', 'b'], [true, false])));
// Zip: [[1,"a",true],[2,"b",false]]
console.log('Range (0, 5):', d3.range(5));
// Range (0, 5): [0, 1, 2, 3, 4]
console.log('Range (1, 5, 0.5):', d3.range(1, 5, 0.5));
// Range (1, 5, 0.5): [1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5]
console.log('Ticks (0, 10, 5):', d3.ticks(0, 10, 5));
// Ticks (0, 10, 5): [0, 2, 4, 6, 8, 10] (example output, actual count may vary slightly)

The d3-array utilities are invaluable for:

  • Data Cleaning & Preparation: Calculating extents for scales, summing values for pie charts, averaging data.
  • Statistical Analysis: Computing variance, standard deviation, quantiles for understanding data distributions.
  • Algorithm Implementation: Using bisection for efficient searching in sorted data (e.g., for tooltips on time series).
  • Generating Data Structures: Creating ranges for iteration, Cartesian products for heatmaps, or tick values for axes.

Explore the full capabilities of this module in the d3-array documentation.