首页 > 解决方案 > DC.JS/Crossfilter:具有线性 x 轴的条形图的 y 轴百分比?

问题描述

我想在 dc.js 条形图的 y 轴上显示百分比,该百分比可以在过滤图表本身或其他一些图表时动态变化。

这是我的情况:

var ndx = crossfilter(dataCsvInitial);
var all = ndx.groupAll();
var accCredLimDim = ndx.dimension(function(d) { return d.acct_curr_crlimit;});

然后,我按箱分组:

var value_range_credlim = maxCredLim - minCredLim;  // defined earlier...
var nb_of_bins_credlim = 50,
    bin_width_credlim = value_range_credlim/nb_of_bins_credlim;
var accCredLimGrp = accCredLimDim.group(function(d) {return Math.floor(d/bin_width_credlim)*bin_width_credlim;});

并绘制我的条形图:

 var creditBar = dc.barChart("#creditDistrib");
        creditBar
            .width(600)
            .height(250)
            .margins({top: 10, right: 50, bottom: 30, left: 50})
            .dimension(accCredLimDim)
            .group(accCredLimGrp)
            .transitionDuration(500)
            .x(d3.scaleLinear().domain([minCredLim, maxCredLim]))
            .xUnits(function(){return nb_of_bins_credlim;})
            .elasticY(true)
            .brushOn(true)
            .xAxisLabel("Credit Limit")

yAxis().tickFormat()我通过自定义条形图的属性,将刻度值除以当前过滤的总行数,成功地完成了我最初想要的操作:

    creditBarChart.yAxis().tickFormat(function (d) {
            return 100*d/all.value() + '%';
        });

每次进行转换时,我都会重新计算这些刻度,因为我的 y 轴是弹性的:

        creditBar
            .on("pretransition", function(){

            creditBar.yAxis().tickFormat(function (d) {
                if (!creditBar.hasFilter()){
                    return Math.trunc(100*d/all.value()) + '%';
                }
            });
        });

如您所见,在过滤条形图时,我不会更新刻度。事实上,当它被过滤时,我希望刻度保持不变,因为 y 轴不应该改变。但是,因为我将刻度值除all.value()以此规则,所以在过滤条形图本身时不起作用。显示的百分比显然是错误的。

这个问题非常接近解决我的问题:链接,但它仅适用于分类条形图......

如何在 y 轴刻度上显示百分比,在过滤其他图表时以及在过滤图表本身时会改变值?all.value()除了过滤指定图表的影响之外,是否有一种计算方法?

谢谢!

标签: dc.jscrossfilter

解决方案


由于您希望 groupAll 不观察此图表上的过滤器,因此您应该使用图表维度的 groupAll而不是 crossfilter 对象上的那个。从文档:

注意:分组与交叉过滤器的当前过滤器相交,关联维度的过滤器除外。因此,组方法只考虑满足除此维度过滤器之外的所有过滤器的记录。因此,如果支付的交叉过滤器按类型和总计过滤,则 groupAll by total 仅观察按类型过滤。

这有点拗口,但我希望意图是明确的。

var accCredLimDim = ndx.dimension(function(d) { return d.acct_curr_crlimit;});
var all = accCredLimDim.groupAll();

一旦你这样做了,你就不必在tickFormat定义中添加 if 语句:

creditBar
    .on("pretransition", function(){
        creditBar.yAxis().tickFormat(function (d) {
            return Math.trunc(100*d/all.value()) + '%';
        });
    });

if 语句不正确有几个原因。首先,这个图表上可能有一个过滤器,也可能有其他图表上的过滤器。其次,您调用的任何访问器,例如tickFormat,每次调用时都需要返回一个值。但是undefined如果此图表上有任何过滤器,这将返回,因为这是 JS 中的默认返回值。


推荐阅读