create multiple charts from data groups of the same column

我与影子孤独终老i 提交于 2019-12-20 02:59:05

问题


How to make this dashboard

from this data

time,group_name,value
15/10/2017 15:36:15,group-1,1
15/10/2017 15:36:15,group-2,1
15/10/2017 15:36:15,group-2,1
15/10/2017 15:36:15,group-2,1
15/10/2017 15:36:16,group-1,1
15/10/2017 15:36:16,group-3,1
15/10/2017 15:36:16,group-1,1
15/10/2017 15:36:16,group-3,1
15/10/2017 15:36:17,group-3,1
15/10/2017 15:36:17,group-3,1
15/10/2017 15:36:17,group-1,1
15/10/2017 15:36:17,group-2,1
15/10/2017 15:36:18,group-1,1
15/10/2017 15:36:18,group-1,1
15/10/2017 15:36:18,group-2,1
15/10/2017 15:36:18,group-1,1
15/10/2017 15:36:19,group-3,1
15/10/2017 15:36:19,group-2,1
15/10/2017 15:36:19,group-2,1
15/10/2017 15:36:19,group-1,1

using dc.js?

Thank you in advance.


回答1:


You can do this by first dimensioning/grouping by both the time and group columns, then using a fake group to split one group into many.

I don't have access to your data (it's better to paste your data as text when asking a question), so I whipped up an example using data from one of the dc.js examples. The data looks like this:

Expt,Run,Speed
1,1,850
1,2,740
1,3,900
1,4,1070
1,5,930
1,6,850
...
2,1,960
2,2,940
2,3,960
2,4,940
2,5,880
2,6,800

There are two important steps. First we need to create a dimension and group keyed on both the X dimension and the dimension to split by. In this case, we want Run to be the X dimension, and we want to split by Expt. We'll put Run first. The group is normal.

var runExptDim = cf.dimension(function(d) {
  return [d.Run, d.Expt];
});
var runExptGroup = runExptDim.group().reduceSum(function(d) {
  return d.Speed;
});

Now we need a fake group to split the original group by the second key. Here's a function which will allow us to construct fake groups for all the values of Expt:

function split_group(group2d) {
  return {
    subgroup: function(key) {
      return {
        all: function() {
          return group2d.all().filter(function(kv) {
            return kv.key[1] === key;
          }).map(function(kv) {
            return {key: kv.key[0], value: kv.value};
          }).sort(function(a, b) {
            return a.key - b.key;
          })
        }
      };
    }
  };
}

There's no magic here. When a subgroup's .all() method is called, it pulls the data from the original group, filters the data using the second part of the key, and removes the second part of the key using .map().

Finally it also has to sort the data because multikeys tend to mess up the ordering, because the data is cast to strings for sorting when you use multikeys.

Grab the subgroups like this:

var splitGroup = split_group(runExptGroup);
var runGroup1 = splitGroup.subgroup(1),
  runGroup2 = splitGroup.subgroup(2),
  runGroup3 = splitGroup.subgroup(3);

Since we've got a strange dimension, it's not clear what dimension to specify to the charts. The simplest thing to do is create another dimension on the X axis:

var runDim = cf.dimension(function(d) {
  return d.Run;
});

However, this will cause the chart to filter itself. I'll probably revisit my answer later and correct this.

A chart initialization looks like this:

var line1 = dc.lineChart('#line1')
  .width(400).height(200)
  .dimension(runExptGroup)
  .group(runGroup1)
  .x(d3.scale.linear())
  .elasticX(true)
  .elasticY(true);

This doesn't cover your styling needs, but you can take a look at the sparkline example for some hints there.

Here's an example fiddle: https://jsfiddle.net/gordonwoodhull/og68rkqz/

Hope this helps!

EDIT: showing totals in number display

To display the totals of each split group, you can create a "fake groupAll" that takes the sum of values:

  function total_group(group) {
    return {
      value: () => d3.sum(group.all(), kv => kv.value)
    };
  }

The number display can take either a groupAll object with .total() method or a regular group, in which case it'll find the max of .all()

Strangely, it needs the identity value accessor when working with a groupAll. Putting it all together:

  var identity = x => x;

  var number1 = dc.numberDisplay('#num1')
    .valueAccessor(identity)
    .group(total_group(runGroup1));

Fork of your fiddle: https://jsfiddle.net/gordonwoodhull/aj1m9ysg/1/



来源:https://stackoverflow.com/questions/46757188/create-multiple-charts-from-data-groups-of-the-same-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!