remove empty bins with reduce Add Remove function not working

南笙酒味 提交于 2019-12-24 05:54:10

问题


I'm looking for a solution in how I can remove empty bins when using a reduce Add/Remove function.

I have a jsfiddle here

Empty bins are removed when I want to provide a simple sum of 'Points', but not when I want to use an average calculation and using the valueAccessor in the charts.

My data is set up as follows:

{Season:"2016/17",
Manager:"Alan Curtis",
Points:1,
Formation:"4231",
date:"01 February 2017"},

{Season:"2016/17",
Manager:"Paul Clement",
Points:1,
Formation:"442",
date:"01 February 2018"},

{Season:"2015/16",
Manager:"Paul Clement",
Points:3,
Formation:"433",
date:"01 May 2017"},

And my aim is to provide a 'Points Per Game' average, by 'Manager', and also by 'Formation'.

I'm using the reduce Add/Remove functions:

function reduceAdd(p, v) {
    p.total += v.Points;
    ++p.count;
    p.ppg = d3.round((p.total / p.count), 2);
    return p;
    }

function reduceRemove(p, v) {
    p.total -= v.Points;
    --p.count;
    p.ppg = d3.round((p.total / p.count), 2);
    return p;
    }

function reduceInitial() {
    return {
        total: 0,
        count: 0,
        ppg: 0,
        };
    }

and the remove empty bins code:

function remove_empty_bins(source_group) {
return {
    all:function () {
        return source_group.all().filter(function(d) {
            return d.value !=0;
        });
    }
};
}

My charts code:

managerChart
    .dimension(dimManager)
    .group(ManagerPPGGroup)
    .ordering(function(p) { return -p.value.ppg })
    .renderLabel(false)
    .othersGrouper(null)
    .renderTitle(false)
    .renderTitleLabel(true)
    .margins({top: 10, left: 10, right: 20, bottom: 80})
    .valueAccessor(function(p) 
        { if (p.value.ppg >0) {
        return p.value.ppg } else { return "n/a"}; });

formationChart
    .dimension(dimFormation)
    .group(filteredFormationPPGGroup)
    .ordering(function(p) { return -p.value.ppg })
    .renderLabel(false)
    .cap(10)
    .elasticX(true)
    .renderTitle(false)
    .renderTitleLabel(true)
    .margins({top: 10, left: 10, right: 20, bottom: 80})
    .valueAccessor(function(p) { return p.value.count > 0 ? p.value.ppg : "not used"; });

Everything works fine, apart from empty bins are not removed when a filter is applied.

I have tried all sorts of things to try and fix the issue, changing the valueAccessor of the charts and the remove_empty_bins function but nothing seems to work.

My current workaround is to provide "not used" text on the graph so users know the Manager didn't use the formation, but I'd prefer to remove empty bins as intended.

Thanks in advance for your help.


回答1:


Yes, remove_empty_bins needs to be adjusted if the reduction produces an object instead of just a number.

I can't think of any general way to do this that won't make it inefficient,* so let's adjust the function for this use-case:

function remove_empty_bins(source_group) {
    return {
        all:function () {
            return source_group.all().filter(function(d) {
                return d.value.total != 0;
            });
        }
    };
}

We just need to pull .total out of the object, because an object (almost) never equals zero.

As a bonus, I've also set the bars to a fixed height in your fiddle:

formationChart
    .fixedBarHeight(30)

Otherwise when there is a single bar, it will grow to fit the entire area, which many people consider ugly.

I also applied filtering to the managers rowChart. Fork of your fiddle: https://jsfiddle.net/gordonwoodhull/qw0oe8ea/6/

* Maybe it's time to refactor this into remove_bins() with a predicate? But that won't be terse until the no-arrow-function browsers go away.



来源:https://stackoverflow.com/questions/44354064/remove-empty-bins-with-reduce-add-remove-function-not-working

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!