How to create equal frequency (depth) bins with D3?

40 views Asked by At

You can create equal width bins with D3 like this:

const arr = [0, 0, 1, 10, 100, 102, 200, 253, 10000]
const bin_gen = d3.bin()
const bins = bin_gen(arr)

Puts the data into these bins:

[
    [
        0,
        0,
        1,
        10,
        100,
        102,
        200,
        253
    ],
    [],
    [],
    [],
    [],
    [
        10000
    ]
]

with these thresholds:

[
    [0, 2000],
    [2000, 4000],
    [4000, 6000],
    [6000, 8000],
    [8000, 10000],
    [10000, 12000]
]

Instead, what I want is for there to be an approximately equal number of observations in each bin, with unequal threshold widths. Is it possible that you can only create equal width bins and not equal depth/frequency bins with D3?

1

There are 1 answers

7
BallpointBen On

If you put your data in a sorted list, then you can simply take the non-overlapping chunks.

// create dummy data, sorted by stringification
const arr = [...Array(23)].map((_, i) => i);
arr.sort();

// get chunk sizes
const n_chunks = 5;
const default_chunk_size = Math.floor(arr.length / n_chunks);
const n_initial_larger_chunks = arr.length % n_chunks;

let index = 0;
const chunks = [];
for (let i = 0; i < n_chunks; i++) {
    let sz = default_chunk_size;
    if (i < n_initial_larger_chunks) {
        sz += 1;
    }

    chunks.push(arr.slice(index, index + sz));
    index += sz;
}

console.log(chunks);
[[0, 1, 10, 11, 12], [13, 14, 15, 16, 17], [18, 19, 2, 20, 21], [22, 3, 4, 5], [6, 7, 8, 9]]