Как я могу заполнить пробелы в графике серии dc.js? - PullRequest
0 голосов
/ 29 июня 2018

У меня есть следующий график серии dc.js :

var data = [
  {day: 1, service: 'ABC', count: 100},
  {day: 2, service: 'ABC', count: 80},
  {day: 4, service: 'ABC', count: 10},
  {day: 7, service: 'XYZ', count: 380},
  {day: 8, service: 'XYZ', count: 400}
];
var ndx = crossfilter(data);
var dim = ndx.dimension(function (d) { return [d.service, d.day]; });
var grp = dim.group().reduceSum(function(d) { return +d.count; });
var chart = dc.seriesChart('#graph')
  .width(620)
  .height(175)
  .chart(function(c) { return dc.lineChart(c).renderArea(true);})
  .dimension(dim)
  .group(grp)
  .seriesAccessor(function(d) { return d.key[0]; })
  .keyAccessor(function(d) { return d.key[1]; })
  .x(d3.scaleLinear().domain([1, 8]))
  .legend(dc.legend().horizontal(true).x(80))
  .render();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.4/dc.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.4/dc.css"/>
<div id="graph"></div>

Это работает, как и ожидалось ... но, поскольку в моих данных есть "пробелы", это выглядит не очень хорошо. Есть ли способ указать dc.js по умолчанию 0 точек, где нет данных для определенного ряда?

В принципе, я хочу получить этот результат, но без необходимости создавать разные группы для каждой серии и собирать их вместе:

var data = [
  {day: 1, service: 'ABC', count: 100},
  {day: 2, service: 'ABC', count: 80},
  {day: 4, service: 'ABC', count: 10},
  {day: 7, service: 'XYZ', count: 380},
  {day: 8, service: 'XYZ', count: 400}
];
var ndx = crossfilter(data);
var dim = ndx.dimension(function (d) { return d.day; });
var grpABC = dim.group().reduceSum(function(d) { return d.service === 'ABC' ? +d.count : 0; });
var grpXYZ = dim.group().reduceSum(function(d) { return d.service === 'XYZ' ? +d.count : 0; });
var chart = dc.lineChart('#graph')
  .width(620)
  .height(175)
  .dimension(dim)
  .group(grpABC)
  .stack(grpXYZ)
  .renderArea(true)
  .x(d3.scaleLinear().domain([1, 8]))
  .legend(dc.legend().horizontal(true).x(80))
  .render();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.4/dc.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.4/dc.css"/>
<div id="graph"></div>

Есть ли способ добиться того же самого с помощью диаграммы в первом примере?

Я видел этот вопрос , который может быть похожим, но они используют NVD3.js и Underscore. Вместо этого у нас есть jQuery, d3.js и dc.js.

1 Ответ

0 голосов
/ 29 июня 2018

FAQ dc.js содержит раздел о данных предварительной обработки . В этом случае вы хотите убедиться, что все пустые значения заполнены нулями, и ensure_group_bins довольно близко к тому, что вы хотите.

Здесь я адаптировал его так, чтобы он брал требуемые ячейки в виде массива, а не в качестве аргументов, потому что нам нужно много корзин - декартово произведение всех служб и всех дней. Для удобства D3v4 содержит d3.cross именно для этой цели.

Тогда мы просто обертываем нашу группу фальшивой группой, созданной ensure_group_bins, и мы уходим!

Интересно, что это раскрывает подробности о ваших данных, которые были затемнены ранее - поскольку линейный график рисует только те точки, где у него есть данные, ранее было неясно, что служба ABC / день 3 равна нулю.

function ensure_group_bins(source_group, bins) {
return {
    all:function () {
        var result = source_group.all().slice(0), // copy original results (we mustn't modify them)
            found = {};
        result.forEach(function(d) {
            found[d.key] = true;
        });
        bins.forEach(function(d) {
            if(!found[d])
                result.push({key: d, value: 0});
        });
        return result;
    }
};
};
var needed = d3.cross(['ABC', 'XYZ'], d3.range(1,8));

var data = [
  {day: 1, service: 'ABC', count: 100},
  {day: 2, service: 'ABC', count: 80},
  {day: 4, service: 'ABC', count: 10},
  {day: 7, service: 'XYZ', count: 380},
  {day: 8, service: 'XYZ', count: 400}
];
var ndx = crossfilter(data);
var dim = ndx.dimension(function (d) { return [d.service, d.day]; });
var grp = dim.group().reduceSum(function(d) { return +d.count; });
grp = ensure_group_bins(grp, needed);
var chart = dc.seriesChart('#graph')
  .width(620)
  .height(175)
  .chart(function(c) { return dc.lineChart(c).renderArea(true);})
  .dimension(dim)
  .group(grp)
  .seriesAccessor(function(d) { return d.key[0]; })
  .keyAccessor(function(d) { return d.key[1]; })
  .x(d3.scaleLinear().domain([1, 8]))
  .legend(dc.legend().horizontal(true).x(80))
  .render();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.4/dc.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.4/dc.css"/>
<div id="graph"></div>
...