UNPKG

@data-ui/histogram

Version:

React + d3 library for creating histograms

64 lines (60 loc) 2.73 kB
import { histogram as d3Histogram, extent as d3Extent } from 'd3-array'; import { scaleLinear } from 'd3-scale'; var DEFAULT_BIN_COUNT = 10; /* * handles binning of numeric data by series index * if binValues are passed, ignores other bin values that are encountered * * returns an object of bins keyed on series index with the following shape * { * [seriesIdx]: Array<Object{ * bin0: String, * bin1: String, * data: Array<datum>, * count: Number, * id: String, * }>, * } */ export default function binNumericData(_ref) { var allData = _ref.allData, _ref$binCount = _ref.binCount, userBinCount = _ref$binCount === void 0 ? DEFAULT_BIN_COUNT : _ref$binCount, binValues = _ref.binValues, limits = _ref.limits, rawDataByIndex = _ref.rawDataByIndex, valueAccessor = _ref.valueAccessor; var binCount = Array.isArray(binValues) ? binValues.length : userBinCount; var binsByIndex = {}; var histogram = d3Histogram(); var extent = d3Extent(allData, valueAccessor); if (binValues) { // account for extent of binValues if passed var binExtent = d3Extent(binValues); extent = [Math.min(binExtent[0], extent[0]), Math.max(binExtent[1], extent[1])]; } var scale = scaleLinear().domain(extent).nice(binCount); histogram.domain(limits || scale.domain()).thresholds(binValues || scale.ticks(binCount)); Object.keys(rawDataByIndex).forEach(function (index) { var data = rawDataByIndex[index]; var seriesBins = histogram.value(valueAccessor)(data); // if the last bin equals the upper bound of the second to last bin, combine them // see https://github.com/d3/d3-array/issues/46#issuecomment-269873644 var lastBinIndex = seriesBins.length - 1; var lastBin = seriesBins[lastBinIndex]; var nextToLastBin = seriesBins[lastBinIndex - 1]; var shouldCombineEndBins = nextToLastBin && nextToLastBin.x1 === lastBin.x0 && lastBin.x1 === lastBin.x0; var filteredBins = shouldCombineEndBins ? seriesBins.slice(0, -1) : seriesBins; binsByIndex[index] = filteredBins.map(function (bin, i) { return { bin0: bin.x0, // if the upper limit equals the lower one, use the delta between this bin and the last bin1: bin.x0 === bin.x1 ? i > 0 && bin.x0 + bin.x0 - seriesBins[i - 1].x0 || bin.x1 + 1 : bin.x1, data: [].concat(bin).concat(shouldCombineEndBins && (shouldCombineEndBins && i === lastBinIndex - 1 ? lastBin : [])), // if the last bin was inclusive / omitted, add its count to the last bin count: bin.length + (shouldCombineEndBins && i === lastBinIndex - 1 ? lastBin.length || 0 : 0), id: i.toString() }; }); }); return binsByIndex; }