维度1上的条形图,维度2上的条形图 [英] Bar Chart on Dimension-1 and Stacked by Dimension-2

查看:87
本文介绍了维度1上的条形图,维度2上的条形图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘要



我想显示一个条形图,其尺寸为天,并按不同的类别堆叠(例如,x轴=天,堆叠=类别1 )。我可以手动执行此操作,因为我可以将if-then写入零或显示数量,但是我想知道是否有系统的方法可以做到这一点。



JSFiddle https://jsfiddle.net/wostoj/rum53tn2/



详细信息



我有包含日期​​,数量和其他分类器的数据。出于这个问题的目的,我可以将其简化为:

  data = [
{day:1,cat : a,数量:25},
{天:1,猫: b,数量:15},
{天:1,猫: b,数量:10},
{日:2,猫:'a',数量:90},
{天:2,猫:'a',数量:45},
{天:2,猫:'b',数量:15},
]

我可以设置一个酒吧的图表,它显示了总单位,我可以按如下所示手动添加 a和 b的堆栈。

  var dayDim = xf.dimension(_ => _.day); 
var bar = dc.barChart(#chart);
bar
.dimension(dayDim)
.group(dayDim.group()。reduceSum(
_ => _.cat ==='a'?_.quantity :0
))
.stack(dayDim.group()。reduceSum(
_ => _.cat ==='b'?_。数量:0
));

但是,当我的数据只有2个类别时,这很容易,但是我想知道d将其缩放到10个或未知数量的类别。我想我要尝试的伪代码是这样的

  dc.barChart(#chart) 
.dimension(xf.dimension(_ => _.day))
.stackDim(xf.dimension(_ => _.cat))
.stackGroup(xf.dimension (_ => _.cat).group()。reduceSum(_ => _.quantity));


解决方案

我在您的其他问题,但为什么不在这里对此稍作扩展。



在dc.js常见问题解答中,有一种用于自定义归约的标准模式,可一次减少多个值。



假设您有一个名为 type 的字段,该字段确定该行中的值的类型以及该值在名为 value 的字段中(在您的情况下为 cat quantity )。然后

  var group = Dimensions.group()。reduce(
function(p,v){//添加
p [v.type] =(p [v.type] || 0)+ v.value;
return p;
},
function(p,v){ //移除
p [v.type]-= v.value;
return p;
},
function(){//初始
return {};
});

将每个bin的所有行减少为一个对象,其中键是类型,值是



此方法的工作方式是,当crossfilter遇到新键时,它首先使用初始函数来产生新值。在这里,该值是一个空对象。 p 是bin的前一个值, v 是当前行。因为我们从一个空白对象开始,所以我们必须确保初始化每个值。 (p [v.type] || 0)将确保我们从 0 开始,而不是从 undefined ,因为 undefined + 1 NaN ,我们讨厌NaN。



在删除功能中我们不必格外小心,因为从存储箱中删除行的唯一方法是是否将其添加到存储箱中,因此 p [v.type] 中必须有一个数字。



现在每个垃圾箱都包含一个对象使用所有减少的值,堆栈混合为 .group() .stack()提供了有用的额外参数允许我们指定组/堆栈的名称以及访问器。



例如,如果要提取 a b 从我们堆栈的对象中,我们可以使用:

  .group(group,'a',kv => kv.value.a)
.stack(group,'b',kv => kv.value.b)

它是虽然不太方便,但是您可以使用这些技术来以编程方式将堆栈添加到图表中(请参见源代码)。


Summary

I want to display a bar chart whose dimension is days and is stacked by a different category (i.e. x-axis = days and stack = category-1). I can do this "manually" in that I can write if-then's to zero or display the quantity, but I'm wondering if there's a systematic way to do this.

JSFiddle https://jsfiddle.net/wostoj/rum53tn2/

Details

I have data with dates, quantities, and other classifiers. For the purpose of this question I can simplify it to this:

data = [
 {day: 1, cat: 'a', quantity: 25},
 {day: 1, cat: 'b', quantity: 15},
 {day: 1, cat: 'b', quantity: 10},
 {day: 2, cat: 'a', quantity: 90},
 {day: 2, cat: 'a', quantity: 45},
 {day: 2, cat: 'b', quantity: 15},
]

I can set up a bar chart, by day, that shows total units and I can manually add the stacks for 'a' and 'b' as follows.

var dayDim = xf.dimension(_ => _.day);
var bar = dc.barChart("#chart");
bar
  .dimension(dayDim)
  .group(dayDim.group().reduceSum(
    _ => _.cat === 'a' ? _.quantity : 0
   ))
  .stack(dayDim.group().reduceSum(
    _ => _.cat === 'b' ? _.quantity : 0
   ));

However, this is easy when my data has only 2 categories, but I'm wondering how I'd scale this to 10 or an unknown number of categories. I'd imagine the pseudo-code I'm trying to do is something like

dc.barChart("#chart")
  .dimension(xf.dimension(_ => _.day))
  .stackDim(xf.dimension(_ => _.cat))
  .stackGroup(xf.dimension(_ => _.cat).group().reduceSum(_ => _.quantity));

解决方案

I mentioned this in my answer to your other question, but why not expand on it a little bit here.

In the dc.js FAQ there is a standard pattern for custom reductions to reduce more than one value at once.

Say that you have a field named type which determines which type of value is in the row, and the value is in a field named value (in your case these are cat and quantity). Then

var group = dimension.group().reduce(
    function(p, v) { // add
        p[v.type] = (p[v.type] || 0) + v.value;
        return p;
    },
    function(p, v) { // remove
        p[v.type] -= v.value;
        return p;
    },
    function() { // initial
        return {};
    });

will reduce all the rows for each bin to an object where the keys are the types and the values are the sum of values with that type.

The way this works is that when crossfilter encounters a new key, it first uses the "initial" function to produce a new value. Here that value is an empty object.

Then for each row it encounters which falls into the bin labelled with that key, it calls the "add" function. p is the previous value of the bin, and v is the current row. Since we started with a blank object, we have to make sure we initialize each value; (p[v.type] || 0) will make sure that we start from 0 instead of undefined, because undefined + 1 is NaN and we hate NaNs.

We don't have to be as careful in the "remove" function, because the only way a row will be removed from a bin is if it was once added to it, so there must be a number in p[v.type].

Now that each bin contains an object with all the reduced values, the stack mixin has helpful extra parameters for .group() and .stack() which allow us to specify the name of the group/stack, and the accessor.

For example, if we want to pull items a and b from the objects for our stacks, we can use:

.group(group, 'a', kv => kv.value.a)
.stack(group, 'b', kv => kv.value.b)

It's not as convenient as it could be, but you can use these techniques to add stacks to a chart programmatically (see source).

这篇关于维度1上的条形图,维度2上的条形图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆