UNPKG

@visactor/vdataset

Version:

data processing tool

131 lines (128 loc) 7.96 kB
import { isNil, isArray } from "@visactor/vutils"; const subBin = (data, options) => { var _a, _b, _c, _d; const {numBins: numBins, thresholds: thresholds, countName: countName, percentageName: percentageName, valuesName: valuesName, countField: countField, field: field, n: n, x0Name: x0Name, x1Name: x1Name} = options, groupField = options.groupField, usingGroup = Array.isArray(groupField) ? groupField.length > 0 : !!groupField, out = []; if (!usingGroup) for (let i = 0; i < numBins; i++) { const rec = { [x0Name]: thresholds[i], [x1Name]: thresholds[i + 1], [countName]: 0 }; options.includeValues && (rec[valuesName] = []), out.push(rec); } const binGroupCounts = usingGroup ? new Array(numBins).fill(0).map((() => new Map)) : [], binGroupValues = usingGroup ? new Array(numBins).fill(0).map((() => new Map)) : [], groupKeyOrder = [], groupKeySet = new Set, groupRepr = new Map; for (let i = 0; i < n; i++) { const v = data[i][field]; if (null == v) continue; const num = +v; if (Number.isFinite(num)) for (let j = 0; j < numBins; j++) { const left = thresholds[j], right = thresholds[j + 1]; if (num >= left && num < right || j === numBins - 1 && num <= right) { const datumCount = null !== (_a = data[i][countField]) && void 0 !== _a ? _a : 1; if (usingGroup) { let gk; gk = isArray(groupField) ? groupField.map((f => String(data[i][f]))).join("||") : String(data[i][groupField]); const m = binGroupCounts[j], prev = null !== (_b = m.get(gk)) && void 0 !== _b ? _b : 0; if (m.set(gk, prev + datumCount), groupKeySet.has(gk) || (groupKeySet.add(gk), groupKeyOrder.push(gk), isArray(groupField) ? groupRepr.set(gk, Object.fromEntries(groupField.map((f => [ f, data[i][f] ])))) : groupRepr.set(gk, data[i][groupField])), options && options.includeValues) { const vv = binGroupValues[j]; vv.has(gk) || vv.set(gk, []); const arr = vv.get(gk); arr && arr.push(data[i]); } } else out[j][countName] += datumCount; options && options.includeValues && !usingGroup && out[j][valuesName].push(data[i]); break; } } } let totalCount = 0; const finalOut = []; if (usingGroup) { for (let j = 0; j < numBins; j++) for (const gk of groupKeyOrder) { const sum = null !== (_c = binGroupCounts[j].get(gk)) && void 0 !== _c ? _c : 0, rec = { [x0Name]: thresholds[j], [x1Name]: thresholds[j + 1], [countName]: sum }, repr = null !== (_d = groupRepr.get(gk)) && void 0 !== _d ? _d : {}; if (isArray(groupField)) for (const f of groupField) rec[f] = repr[f]; else groupField && (rec[groupField] = repr); options && options.includeValues && (rec[valuesName] = binGroupValues[j].get(gk) || []), finalOut.push(rec), totalCount += sum; } const denominator = totalCount; for (const r of finalOut) r[percentageName] = denominator > 0 ? r[countName] / denominator : 0; } else { for (let i = 0, len = out.length; i < len; i++) totalCount += out[i][countName]; for (let i = 0, len = out.length; i < len; i++) out[i][percentageName] = totalCount > 0 ? out[i][countName] / totalCount : 0, finalOut.push(out[i]); } return finalOut; }; export const bin = (data, options) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; const field = null == options ? void 0 : options.field; if (!field) return []; const countField = options.countField, n = data.length; let thresholds, min = 1 / 0, max = -1 / 0; if (options.extent) min = options.extent[0], max = options.extent[1]; else for (let i = 0; i < n; i++) { const v = data[i][field]; if (isNil(v)) continue; const num = +v; Number.isFinite(num) && (num < min && (min = num), num > max && (max = num)); } if (!Number.isFinite(min) || !Number.isFinite(max) || 0 === n) return []; if (options.thresholds && options.thresholds.length) thresholds = options.thresholds.slice(), thresholds.sort(((a, b) => a - b)); else if ("number" == typeof options.step && options.step > 0) { const stepSize = options.step; let startMin = min; for (options.extent || (startMin = Math.floor(min / stepSize) * stepSize), thresholds = [ startMin ]; startMin <= max; ) startMin += stepSize, thresholds.push(startMin); } else { let bins = options.bins && options.bins > 0 ? Math.floor(options.bins) : 10; if (max - min > 1) { const start = Math.floor(min), stepSizeInt = Math.ceil((max - start) / bins); thresholds = new Array(bins + 1); for (let i = 0; i <= bins; i++) if (thresholds[i] = start + stepSizeInt * i, thresholds[i] > max) { bins = i, thresholds.length = bins + 1; break; } } else { const stepSize = (max - min) / bins; thresholds = new Array(bins + 1); for (let i = 0; i <= bins; i++) if (thresholds[i] = min + stepSize * i, thresholds[i] > max) { bins = i, thresholds.length = bins + 1; break; } } } const numBins = Math.max(0, thresholds.length - 1); if (0 === numBins) return []; const x0Name = null !== (_b = null === (_a = options.outputNames) || void 0 === _a ? void 0 : _a.x0) && void 0 !== _b ? _b : "x0", x1Name = null !== (_d = null === (_c = options.outputNames) || void 0 === _c ? void 0 : _c.x1) && void 0 !== _d ? _d : "x1", countName = null !== (_f = null === (_e = options.outputNames) || void 0 === _e ? void 0 : _e.count) && void 0 !== _f ? _f : "count", valuesName = null !== (_h = null === (_g = options.outputNames) || void 0 === _g ? void 0 : _g.values) && void 0 !== _h ? _h : "values", percentageName = null !== (_k = null === (_j = options.outputNames) || void 0 === _j ? void 0 : _j.percentage) && void 0 !== _k ? _k : "percentage", facetField = isArray(null == options ? void 0 : options.facetField) ? null == options ? void 0 : options.facetField : (null == options ? void 0 : options.facetField) ? [ options.facetField ] : [], groupField = isArray(null == options ? void 0 : options.groupField) ? null == options ? void 0 : options.groupField : (null == options ? void 0 : options.groupField) ? [ options.groupField ] : [], normalizedGroupField = groupField.length ? groupField : void 0, subViewOptions = Object.assign(Object.assign({}, options), { numBins: numBins, thresholds: thresholds, countName: countName, percentageName: percentageName, valuesName: valuesName, countField: countField, field: field, n: n, x0Name: x0Name, x1Name: x1Name, groupField: normalizedGroupField }); if (!facetField.length) return subBin(data, subViewOptions); const subViewMap = {}; return data.forEach((dataItem => { const subViewKey = facetField.map((field => null == dataItem ? void 0 : dataItem[field])).join("-&&-"); subViewMap[subViewKey] ? subViewMap[subViewKey].push(dataItem) : subViewMap[subViewKey] = [ dataItem ]; })), Object.values(subViewMap).map((subDataset => { const combinedGroupField = [ ...groupField, ...facetField ]; return subBin(subDataset, Object.assign(Object.assign({}, subViewOptions), { groupField: combinedGroupField.length ? combinedGroupField : void 0, n: subDataset.length })); })).flat(); }; export default bin; //# sourceMappingURL=bin.js.map