-->

dc.js - min value from group per day

2019-04-01 02:29发布

问题:

I have the following data structure and would like to display a lineChart with the minimum value of 'amount' (group) by Day (of date) (dimension).

var data = [
 {date: "2014-01-01", amount: 10},
 {date: "2014-01-01", amount: 1},
 {date: "2014-01-15", amount: 0},
 {date: "2014-01-15", amount: 10 },
 {date: "2014-02-20", amount: 100 },
 {date: "2014-02-20", amount: 10 },
];

Where as I would normally be doing something along the following lines, I'm not sure how to find the min in the group.

var dateDim = facts.dimension(function (d) {return d3.time.day(d.date);});
var dateDimGroup = dateDim.group().reduceSum(function (d) { return d.amount; })

Is this possible? I can't seem to find any examples of this so any help would be really appreciated.

Thanks!

回答1:

You're going to need to keep a custom grouping. The basic idea is that you maintain an array (ordered is best) of all the values in a group. In your add function, you the current value to the array and assign the first value to a 'min' property of the group. In your remove function you remove values, you remove the current value from the array and then assign the first value to the 'min' property (and check if the list is empty, in which case set it to undefined or something along those lines).

You functions will look something like this:

function add(accessor) {
    var i;
    var bisect = crossfilter.bisect.by(function(d) { return d; }).left;
    return function (p, v) {
        // Not sure if this is more efficient than sorting.
        i = bisect(p.valueList, accessor(v), 0, p.valueList.length);
        p.valueList.splice(i, 0, accessor(v));
        p.min = p.valueList[0];
        return p;
    };
};
function remove(accessor) {
    var i;
    var bisect = crossfilter.bisect.by(function(d) { return d; }).left;
    return function (p, v) {
        i = bisect(p.valueList, accessor(v), 0, p.valueList.length);
        // Value already exists or something has gone terribly wrong.
        p.valueList.splice(i, 1);
        p.min = p.valueList[0];
        return p;
    };
};
function initial() {
    return function () {
        return {
            valueList: [],
            min: undefined
        };
    };
}

'accessor' is a function to get at the value you want the minimum of, like in reduceSum. Call each of these functions to return the function you use in the corresponding place in the .group(add, remove, initial) function.

This code is pretty much ripped straight out of reductio, so you could also use reductio and do:

var dateDim = facts.dimension(function (d) {return d3.time.day(d.date);}); var dateDimGroup = reductio().min(function (d) { return d.amount; })(dateDim.group());

Your dateDimGroup will then have a 'min' property that should give you the minimum amount for every date.