【问题标题】:Stackbar chart in dcjs split by dimensiondc js中的堆积条形图按维度拆分
【发布时间】:2019-10-29 18:59:14
【问题描述】:

我正在尝试在 dcjs 中创建堆栈条形图。 dcjs 的堆栈条示例非常清楚,条形图与堆栈的巨大区别在于堆栈功能。堆栈函数将同一组作为输入,它可以将第三个参数作为函数,该函数决定它必须拆分哪个值。我宁愿用一个维度来拆分整个条形图。

假设以下数据点是这样的

data = [
  {activity:"A1",time_taken:10,activity_group:"Master A"},
  {activity:"A2",time_taken:20,activity_group:"Master B"},
  {activity:"A1",time_taken:30,activity_group:"Master C"},
  {activity:"A2",time_taken:15,activity_group:"Master D"}
]

我希望 x 轴上的活动组按其在 y 轴上所用时间的活动进行拆分,如下所示:

我如何做到这一点?

【问题讨论】:

  • “分割整个条形图”的意思是希望每个堆叠的条形图加起来占 Y 轴的 100%?
  • 是的,我想按自己的单位添加它们,而不是使其达到 100%。如果你能看到这个链接pasteboard.co/IEstrBP.png 这表明了我想要的。
  • 你想让它们像这样单独着色吗? dc.js 通常为每个“堆栈”着色一种颜色,因此 Master A 和 Master B 会说是蓝色,Master C 和 Master D 是橙色。在 dc.js 中,每个 X 值的堆栈数必须相同,但您可以通过将任何额外内容归零来解决此问题。如果您想要单独的着色,您可以将每个值放入自己的堆栈中,只要您将域的其余部分归零即可。有很多方法可以做到这一点,不知道你想做什么。
  • 我真的不关心图表的颜色,我对 dc.js 创建的内容感到满意。我想知道如何将活动组之类的维度一分为二来拆分数据。我不确定这种方法。我可以想象有一个维度活动并使用该创建组,它现在给出了 time_taken 的总和,我如何将其拆分到 activity_group ?
  • 请参考我的 jsfiddle jsfiddle.net/goxrt27q 这里我已经设置了相同的设置,我只需要显示按其活动组拆分的每个活动

标签: d3.js dc.js


【解决方案1】:

你的小提琴是在 dc.js 版本 1.7 上的,它已经有五年多的历史了,我无法理解。 :-/

我将它转换为 dc.js 版本 2,它也使用 D3 v3。

dc.js 不擅长展示原始数据,它更多的是展示聚合数据。但在这种情况下,为每个 activity_group 创建一个堆栈可能是有意义的;这样它就会自动分配自己的颜色。

使用 ES6 我们可以像这样得到所有activity_group 的列表:

const stacks = [...new Set(data.map(row => row.activity_group))];

现在让我们按堆栈聚合数据:

var groupActivity = dimByActivity.group().reduce(
    function reduceAdd(p, v) {
        p[v.activity_group] += v.time_taken;
        return p;
    },
    function reduceRemove(p, v) {
        p[v.activity_group] -= v.time_taken;
        return p;
    },
    function reduceInitial() {
        return Object.fromEntries(stacks.map(stack => [stack,0]));
    });

这与stacked bar example 基本相同,只是我们每个activity_group 都有一个堆栈。

请注意,我们在每个 bin 中创建所有堆栈,只是在它们不存在的地方将它们设为零。这是因为 dc.js 期望每个 X 值都有相同的堆栈 - 否则它将无法工作。

与堆积条形示例一样,我们将以编程方式将堆栈添加到图表中,请记住,我们需要为第一个堆栈使用 .group()

function sel_stack(valueKey) {
    return function(d) {
    return d.value[valueKey];
  };
}
// ...
stacks.forEach(function(stack, i) {
  if(i===0)
    chanUtil.group(groupActivity, stack, sel_stack(stack));
  else
    chanUtil.stack(groupActivity, stack, sel_stack(stack));
})

这是输出。为了让图例不重叠,我稍微弄乱了边距和高度,并且可能有更聪明的方法来处理这个问题:

Fork of your fiddle.

正如我所说,这会让 dc.js 做一些它不想做的事情,所以 YMMV!

【讨论】:

  • 结案,谢谢。您的回复让我了解更多这方面的信息并为您做出贡献。
猜你喜欢
  • 1970-01-01
  • 2012-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-05
  • 2018-02-03
  • 1970-01-01
  • 2017-08-29
相关资源
最近更新 更多