如何基于reduceSum后的季度分组使用dc.js生成目标直方图
实现方案
核心思路
crossfilter本身仅支持对原始行数据做维度聚合,不能直接对聚合后的结果二次分组,所以我们通过**fake group(虚拟分组)**的方式实现需求:先按季度聚合总销量,再对季度总销量做分箱计数。
具体代码实现
第一步:聚合每个季度的总销量
先创建季度维度,统计每个季度的全品类销量总和:
// 季度维度,按日期字段分组 const quarterDim = ndx.dimension(d => d.Quarter); // 按季度聚合总销量 const quarterTotalSalesGroup = quarterDim.group().reduceSum(d => d.unitsSold);
第二步:定义分箱用的虚拟分组
自定义函数生成符合crossfilter group规范的虚拟分组,自动对季度总销量做分箱、统计每个分箱对应的季度数量:
/** * 对季度总销量做分箱计数 * @param {Object} quarterGroup 季度总销量的分组对象 * @param {Number} binSize 分箱步长,可自行调整 * @returns {Object} 符合crossfilter group规范的虚拟分组 */ function getBinnedQuarterGroup(quarterGroup, binSize) { return { all: () => { const binMap = {}; // 遍历所有季度的总销量,计算所属分箱 quarterGroup.all().forEach(item => { const binKey = Math.round(item.value / binSize) * binSize; binMap[binKey] = (binMap[binKey] || 0) + 1; }); // 按分箱值排序后返回 return Object.entries(binMap) .map(([key, count]) => ({ key: Number(key), value: count })) .sort((a, b) => a.key - b.key); } }; }
第三步:初始化直方图
用虚拟分组作为直方图的数据源,完成常规配置即可:
const binSize = 10000; // 可根据需求调整分箱大小 const histogramChart = new dc.BarChart('#histogram'); histogramChart .dimension(quarterDim) // 维度使用季度维度即可 .group(getBinnedQuarterGroup(quarterTotalSalesGroup, binSize)) // 传入虚拟分组 .x(d3.scaleLinear()) .xUnits(dc.units.fixed(binSize)) // 指定固定步长的分箱单位 .elasticX(true) .elasticY(true) .xAxisLabel('季度总销量') .yAxisLabel('对应季度数量'); // 渲染图表 histogramChart.render();
补充说明
- 该实现天然支持和其他dc.js图表的过滤联动:其他图表做过滤操作后,季度总销量分组会自动更新,虚拟分组也会实时重算分箱结果。
- 如果需要支持点击直方图刷选对应销量区间的季度,只需额外配置
filterHandler,根据用户选择的区间过滤quarterDim即可。
内容的提问来源于stack exchange,提问作者Marc8932
相关产品推荐
相关产品推荐

