【问题标题】:dc.js apply some, but not all chart selections to numberDisplay, while maintaining the interactions between charts in placedc.js 将一些但不是所有图表选择应用于 numberDisplay,同时保持图表之间的交互到位
【发布时间】:2016-02-12 18:11:30
【问题描述】:

我有一个具有以下行/列结构的数据集(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. 折线图;维度 = dateDim,组 = RevenuePerDate

  2. 饼图;维度 = cat1Dim,组 = 收入 PerCat1

  3. 饼图;维度 = cat2Dim,组 = 收入 PerCat2

除了图表,我还想通过 numberDisplay 显示年初至今的收入值。最初我想通过向 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。 理想情况下,我只想使用一个交叉过滤器实例,但我也愿意接受任何涉及第二个交叉过滤器的建议。

编辑:

根据 Gordon 的评论,我使用了自定义 reduce 函数。而不是 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 不受该维度上的任何选择的影响。

【问题讨论】:

  • 如果您只想忽略一个图表中的过滤器,您可以将您的自定义组放在与该图表相同的维度上(并使用自定义减少而不是全部组)。如果你想忽略多个维度,我认为不使用另一个交叉过滤器是无法做到的。
  • 根据您的 cmets,我使用可行的解决方案编辑了原始帖子。非常适合单个 numberDisplay,感谢您的建议!我也尝试了第二个交叉过滤器的选项;如果您将过滤器从第一个交叉过滤器的图表推送到第二个交叉过滤器,则可以获得相同的结果。由于我仅将其用于单个 numberDisplay,因此您的第一个建议效率更高。
  • 太好了,我很高兴它有效。感谢您发布您的解决方案,因为我相信它会帮助其他人。
  • 能否请您从您的解决方案中给出答案,以便其他人知道该问题已得到解答?

标签: d3.js dc.js crossfilter


【解决方案1】:

根据 Gordon 的评论,我使用了自定义 reduce 函数。而不是 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 不受该维度上的任何选择的影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多