dc.js将一些但不是所有的图表选择应用于numberDisplay,同时保持图表之间的交互

时间:2015-11-11 15:40:30

标签: d3.js dc.js crossfilter

我有一个具有以下行/列结构的数据集( data ):

Date        Category1      Category2       Revenue
30/12/2014  a              x               10    
30/12/2014  b              x               15
31/12/2014  a              x               11
1/1/2015    a              x               13
2/1/2015    a              x               14
2/1/2015    b              x                9
2/1/2015    c              z                4
...

基于数据,我创建了几个维度和组:

var ndx                 = crossfilter(data);
var cat1Dim             = ndx.dimension(function(d) {return d.Category1;});
var revenuePerCat1      = cat1Dim.group().reduceSum(function(d) { return d.Revenue; });
var cat2Dim             = ndx.dimension(function(d) {return d.Category2;});
var revenuePerCat2      = cat2Dim.group().reduceSum(function(d) { return d.Revenue; });
var dateDim             = ndx.dimension(function(d) { return d.Date; });
var revenuePerDate      = dateDim.group().reduceSum(function(d) { return d.Revenue; });

接下来,我创建以下图表:

  1. 折线图; dimension = dateDim,group = revenuePerDate

  2. 一个饼图; dimension = cat1Dim,group = revenuePerCat1

  3. 一个饼图; dimension = cat2Dim,group = revenuePerCat2

  4. 除了图表,我还希望通过数字显示来显示收入的年初至今价值。最初我想通过向reduceSum函数添加一个简单的if条件来实现这一点,其中我将数据减少为仅包含当前年份的项目,如下所示:

    var ytdRev = ndx.groupAll().reduceSum(function(d) { if(d.Date.getFullYear() == curYear) {return d.Revenue;} else{return 0;}});
    

    然后通过以下方式调用包含numberDisplay项的框:

    box_ytd
        .formatNumber("$,.4s")
        .valueAccessor(function(d) {return Math.round(d * 1000) / 1000; })
        .group(ytdRev);
    

    如果选择饼图中显示的某个类别,则此功能完全正常,但如果还开始在折线图中过滤日期范围,则该功能不正确。也就是说,实际上将返回特定选择的“日期 - 迄今”值,而不是年初至今的值。虽然从技术角度来看这种行为是正确的,但我想知道如何指示dc.js,这样它只会在渲染numberDisplay时考虑来自某组图表的图表选择。但是,在饼图中所做的选择应更新折线图中显示的选择和numberDisplay。 理想情况下,我只想使用一个crossfilter实例,但我对任何涉及第二个交叉过滤器的建议持开放态度。

    修改

    根据戈登的评论,我玩了一个自定义缩小功能。而不是ndx.groupAll()我在维度级别上使用.groupAll()应用了以下reduce函数:

    function reduceAdd(p,v) {
        if(v.Date.getFullYear() == curYear)
        p.revenue += +v.Revenue;
        return p;}
    function reduceRemove(p,v) {
        if v.Date.getFullYear() == curYear)
        p.revenue -= +v.Revenue;
        return p;}
    function reduceInitial() {
        return {revenue:0 };}
    
    var ytdRev = dateDim.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial);
    

    numberDisplay中的.valueAccessor从d.value.revenue更改为d.revenue:

    box_ytd
        .formatNumber("$,.4s")
        .valueAccessor(function(d) {return Math.round(d.revenue * 1000) / 1000; })
        .group(ytdRev);
    

    numberDisplay现在将反映饼图中每个选项的当前年份总值。日期选择只会影响饼图的值; numberDisplay与折线图共享相同的尺寸,因此numberDisplay不受该尺寸上任何选择的影响。

1 个答案:

答案 0 :(得分:1)

根据戈登的评论,我玩了一个自定义缩小功能。而不是ndx.groupAll()我在维度级别上使用.groupAll()应用了以下reduce函数:

function reduceAdd(p,v) {
    if(v.Date.getFullYear() == curYear)
    p.revenue += +v.Revenue;
    return p;}
function reduceRemove(p,v) {
    if v.Date.getFullYear() == curYear)
    p.revenue -= +v.Revenue;
    return p;}
function reduceInitial() {
    return {revenue:0 };}

var ytdRev = dateDim.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial);

numberDisplay中的.valueAccessor从d.value.revenue更改为d.revenue:

box_ytd
    .formatNumber("$,.4s")
    .valueAccessor(function(d) {return Math.round(d.revenue * 1000) / 1000; })
    .group(ytdRev);

numberDisplay现在将反映饼图中每个选项的当前年份总值。日期选择只会影响饼图'值; numberDisplay与折线图共享相同的尺寸,因此numberDisplay不受该尺寸上任何选择的影响。