Array manipulation, ordering, searching, summarizing, etc.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Histogram generation and data binning functionality for creating frequency distributions and visualizations. Binning groups discrete samples into consecutive, non-overlapping intervals commonly used in data visualization.
The bin generator creates histogram bins from data, grouping values into intervals for visualization and analysis.
Creates a new bin generator with default settings.
/**
* Creates a new bin generator with default settings
* @returns A configurable bin generator function
*/
function bin(): BinGenerator;
/**
* @deprecated Use bin() instead
* Creates a bin generator (legacy alias for bin)
*/
function histogram(): BinGenerator;
interface BinGenerator {
/**
* Bins the given iterable of data samples
* @param data - The data to bin
* @returns Array of bins, each containing associated elements from input data
*/
(data: Iterable<any>): Bin[];
/**
* Sets or gets the value accessor function
* @param value - Optional accessor function or constant
* @returns The bin generator (if setting) or current accessor (if getting)
*/
value(value?: (d: any, i: number, data: any[]) => number): BinGenerator | ((d: any, i: number, data: any[]) => number);
/**
* Sets or gets the domain (data range) for binning
* @param domain - Domain array [min, max] or function returning domain
* @returns The bin generator (if setting) or current domain (if getting)
*/
domain(domain?: [number, number] | ((values: number[]) => [number, number])): BinGenerator | [number, number] | ((values: number[]) => [number, number]);
/**
* Sets or gets the threshold generator or explicit thresholds
* @param thresholds - Number of bins, array of thresholds, or threshold generator function
* @returns The bin generator (if setting) or current thresholds (if getting)
*/
thresholds(thresholds?: number | number[] | ((values: number[], min: number, max: number) => number | number[])): BinGenerator | number | number[] | ((values: number[], min: number, max: number) => number | number[]);
}
interface Bin extends Array<any> {
/** Lower bound of the bin (inclusive) */
x0: number;
/** Upper bound of the bin (exclusive, except for the last bin) */
x1: number;
}Usage Examples:
import { bin, extent } from "d3-array";
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Basic binning with default settings
const histogram = bin();
const bins = histogram(data);
// Each bin is an array containing the data values that fall within its range
// Each bin has x0 (lower bound) and x1 (upper bound) properties
// Configure bin generator
const customBin = bin()
.domain([0, 10]) // Set explicit domain
.thresholds(5); // Request 5 bins
const customBins = customBin(data);Sets the value accessor function for extracting numeric values from data elements.
/**
* Sets the value accessor function for extracting numeric values
* @param value - Function to extract numeric values from data elements
* @returns The bin generator for method chaining
*/
value(value: (d: any, i: number, data: any[]) => number): BinGenerator;Usage Examples:
import { bin } from "d3-array";
const data = [
{score: 85}, {score: 92}, {score: 78}, {score: 96}, {score: 73}
];
const histogram = bin()
.value(d => d.score) // Extract score property
.thresholds(3); // 3 bins
const bins = histogram(data);
// Bins contain the original objects, grouped by their score valuesSets the domain (data range) that should be binned.
/**
* Sets the domain (data range) that should be binned
* @param domain - [min, max] array or function that computes domain from values
* @returns The bin generator for method chaining
*/
domain(domain: [number, number] | ((values: number[]) => [number, number])): BinGenerator;Usage Examples:
import { bin, extent } from "d3-array";
const data = [1, 2, 3, 4, 5, 15, 16, 17, 18, 19]; // Note the gap
// Default domain uses extent of data
const defaultBin = bin();
// Would create bins covering 1-19
// Custom domain focuses on specific range
const focusedBin = bin()
.domain([1, 10]) // Only bin values 1-10
.thresholds(5);
// Values outside domain (15-19) are ignored
const bins = focusedBin(data);Sets the threshold generator or explicit threshold values for binning.
/**
* Sets the threshold generator or explicit threshold values
* @param thresholds - Number of bins, explicit threshold array, or generator function
* @returns The bin generator for method chaining
*/
thresholds(thresholds: number | number[] | ((values: number[], min: number, max: number) => number | number[])): BinGenerator;Usage Examples:
import { bin, thresholdFreedmanDiaconis, ticks } from "d3-array";
const data = [/* numeric data */];
// Specify number of bins (approximate)
const binByCount = bin().thresholds(10);
// Explicit threshold values
const binExplicit = bin().thresholds([0, 5, 10, 20, 50, 100]);
// Use threshold generator function
const binFreedman = bin().thresholds(thresholdFreedmanDiaconis);
// Custom threshold generator
const binCustom = bin().thresholds((values, min, max) => {
return ticks(min, max, 8); // Nice tick values
});Pre-built functions that determine optimal number of bins based on statistical methods.
Returns the number of bins according to Sturges' formula.
/**
* Returns the number of bins according to Sturges' formula
* @param values - Array of numeric values
* @returns Number of recommended bins
*/
function thresholdSturges(values: number[]): number;Returns the number of bins according to the Freedman–Diaconis rule.
/**
* Returns the number of bins according to the Freedman–Diaconis rule
* @param values - Array of numeric values
* @param min - Minimum value in the dataset
* @param max - Maximum value in the dataset
* @returns Number of recommended bins
*/
function thresholdFreedmanDiaconis(values: number[], min: number, max: number): number;Returns the number of bins according to Scott's normal reference rule.
/**
* Returns the number of bins according to Scott's normal reference rule
* @param values - Array of numeric values
* @param min - Minimum value in the dataset
* @param max - Maximum value in the dataset
* @returns Number of recommended bins
*/
function thresholdScott(values: number[], min: number, max: number): number;Usage Examples:
import { bin, thresholdSturges, thresholdFreedmanDiaconis, thresholdScott } from "d3-array";
const data = [/* large dataset of numeric values */];
// Compare different threshold methods
const sturges = bin().thresholds(thresholdSturges);
const freedman = bin().thresholds(thresholdFreedmanDiaconis);
const scott = bin().thresholds(thresholdScott);
const sturgesBins = sturges(data);
const freedmanBins = freedman(data);
const scottBins = scott(data);
console.log(`Sturges: ${sturgesBins.length} bins`);
console.log(`Freedman-Diaconis: ${freedmanBins.length} bins`);
console.log(`Scott: ${scottBins.length} bins`);import { bin } from "d3-array";
// Generate sample data
const scores = [
72, 85, 90, 78, 92, 88, 76, 95, 83, 87,
91, 79, 86, 89, 94, 81, 77, 93, 84, 80
];
// Create histogram with 5 bins
const histogram = bin()
.domain([70, 100]) // Score range
.thresholds(5); // 5 bins
const bins = histogram(scores);
// Display histogram
bins.forEach((bin, i) => {
console.log(`Bin ${i}: [${bin.x0}, ${bin.x1}) - ${bin.length} students`);
console.log(` Scores: ${bin.join(', ')}`);
});
// Output might be:
// Bin 0: [70, 76) - 2 students
// Scores: 72
// Bin 1: [76, 82) - 5 students
// Scores: 78, 76, 79, 81, 77
// etc.import { bin } from "d3-array";
const transactions = [
{id: 1, amount: 25.50, category: 'food'},
{id: 2, amount: 120.00, category: 'shopping'},
{id: 3, amount: 45.75, category: 'food'},
{id: 4, amount: 300.00, category: 'rent'},
{id: 5, amount: 15.25, category: 'food'},
// ... more transactions
];
// Bin transactions by amount
const amountHistogram = bin()
.value(d => d.amount)
.domain([0, 500])
.thresholds(10);
const amountBins = amountHistogram(transactions);
// Analyze spending patterns
amountBins.forEach((bin, i) => {
const totalAmount = bin.reduce((sum, t) => sum + t.amount, 0);
const avgAmount = totalAmount / bin.length;
console.log(`$${bin.x0}-$${bin.x1}: ${bin.length} transactions, avg $${avgAmount.toFixed(2)}`);
});import { bin, timeDay, timeWeek } from "d3-array";
const events = [
{timestamp: new Date('2023-01-01'), type: 'login'},
{timestamp: new Date('2023-01-02'), type: 'purchase'},
{timestamp: new Date('2023-01-03'), type: 'login'},
// ... more events
];
// Bin events by day
const dailyBins = bin()
.value(d => d.timestamp.getTime())
.thresholds((values, min, max) => {
// Create threshold for each day
const start = new Date(min);
const end = new Date(max);
const thresholds = [];
for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
thresholds.push(d.getTime());
}
return thresholds;
});
const eventsByDay = dailyBins(events);
// Analyze daily activity
eventsByDay.forEach(bin => {
const date = new Date(bin.x0).toDateString();
console.log(`${date}: ${bin.length} events`);
});import { bin, thresholdFreedmanDiaconis, thresholdSturges, thresholdScott } from "d3-array";
function adaptiveHistogram(data, maxBins = 50) {
// Try different threshold methods and pick the best one
const methods = [
{ name: 'sturges', fn: thresholdSturges },
{ name: 'freedman', fn: thresholdFreedmanDiaconis },
{ name: 'scott', fn: thresholdScott }
];
let bestBins = null;
let bestCount = 0;
methods.forEach(method => {
const histogram = bin().thresholds(method.fn);
const bins = histogram(data);
// Prefer method that gives reasonable number of bins
if (bins.length > bestCount && bins.length <= maxBins) {
bestBins = bins;
bestCount = bins.length;
}
});
return bestBins || bin().thresholds(Math.min(maxBins, Math.ceil(Math.sqrt(data.length))))(data);
}
// Usage
const measurements = [/* large array of measurements */];
const optimalBins = adaptiveHistogram(measurements);import { bin, mean, deviation } from "d3-array";
function analyzeDistribution(data) {
const histogram = bin().thresholds(20);
const bins = histogram(data);
// Calculate statistics for each bin
const binStats = bins.map(bin => ({
range: [bin.x0, bin.x1],
count: bin.length,
density: bin.length / data.length,
mean: mean(bin),
stdDev: deviation(bin)
}));
// Find most common range
const maxBin = binStats.reduce((max, bin) =>
bin.count > max.count ? bin : max
);
return {
bins: binStats,
mostCommon: maxBin,
totalBins: bins.length
};
}
const distribution = analyzeDistribution([/* your data */]);
console.log(`Most common range: [${distribution.mostCommon.range.join(', ')}]`);
console.log(`${distribution.mostCommon.count} values (${(distribution.mostCommon.density * 100).toFixed(1)}%)`);Install with Tessl CLI
npx tessl i tessl/npm-d3-array