Home » Javascript » dc.js ordinal stacked barchart with two dimensions, getting NaN values and no stacked bar is displayed

dc.js ordinal stacked barchart with two dimensions, getting NaN values and no stacked bar is displayed

Posted by: admin November 1, 2017 Leave a comment

Questions:

I’m working on creating a stacked bar chart (replicating like this), with CSV data which has 3 columns.
I’m getting the x-axis values displayed but no stacked bar rendered.
I’m having difficulty replicating from the dc.js example mentioned above.

Please see the code here

This is the data in the CSV:

var data = [ {"Name":"Dani","Subject":"Maths","Score":60}, {"Name":"Dani","Subject":"Science","Score":80}, {"Name":"Dani","Subject":"History","Score":70},
{"Name":"Kelly","Subject":"Maths","Score":90}, {"Name":"Kelly","Subject":"Science","Score":100}, {"Name":"Kelly","Subject":"History","Score":55},
{"Name":"Sara","Subject":"Maths","Score":100}, {"Name":"Sara","Subject":"Science","Score":65}, {"Name":"Sara","Subject":"History","Score":60},
{"Name":"James","Subject":"Maths","Score":70}, {"Name":"James","Subject":"Science","Score":80}, {"Name":"James","Subject":"History","Score":90},
{"Name":"Mike","Subject":"Maths","Score":90}, {"Name":"Mike","Subject":"Science","Score":75}, {"Name":"Mike","Subject":"History","Score":80} ]
Answers:

I found some mistakes in your code. Working solution in the hidden snippet below and in this pen.

Firstly, you should define YDimension this way:

var YDimension = XDimension.group().reduce(
  function reduceAdd(p, d) {
    p[d.Subject] = (p[d.Subject]|| 0) + d.Score;
    return p;
  },
  function reduceRemove(p, d) {
    p[d.Subject] = (p[d.Subject]|| 0) - d.Score;
    return p;
  },
  function reduceInitial() {
    return {};})

Here, you count how many scores get peoples for appropriate subject.

Rewrite sel_stack function:

function sel_stack(subjectName) {
  return function(dataItem) {
    return dataItem.value[subjectName];
  };
}

Call chart.stack function in loop like this:

var subjects = ['Maths', 'Science', 'History'];
...
for(var i = 0; i < subjects.length - 1; ++i) {
  chart.stack(
    YDimension,
    subjects[i],
    sel_stack(subjects[i])
  );
}
var data = [ {"Name":"Dani","Subject":"Maths","Score":60}, {"Name":"Dani","Subject":"Science","Score":80}, {"Name":"Dani","Subject":"History","Score":70},
{"Name":"Kelly","Subject":"Maths","Score":90}, {"Name":"Kelly","Subject":"Science","Score":100}, {"Name":"Kelly","Subject":"History","Score":55},
{"Name":"Sara","Subject":"Maths","Score":100}, {"Name":"Sara","Subject":"Science","Score":65}, {"Name":"Sara","Subject":"History","Score":60},
{"Name":"James","Subject":"Maths","Score":70}, {"Name":"James","Subject":"Science","Score":80}, {"Name":"James","Subject":"History","Score":90},
{"Name":"Mike","Subject":"Maths","Score":90}, {"Name":"Mike","Subject":"Science","Score":75}, {"Name":"Mike","Subject":"History","Score":80} ];
var subjects = ['Maths', 'Science', 'History'];

var chart = dc.barChart("#test");

data.forEach(function(x) {
  x.Marks = +x.Marks;
});
var ndx = crossfilter(data);

var XDimension = ndx.dimension(function (d) {return d.Name;});

var YDimension = XDimension.group().reduce(
  function reduceAdd(p, d) {
    p[d.Subject] = (p[d.Subject]|| 0) + d.Score;
    return p;
  },
  function reduceRemove(p, d) {
    p[d.Subject] = (p[d.Subject]|| 0) - d.Score;
    return p;
  },
  function reduceInitial() {
    return {};})

function sel_stack(subjectName) {
  return function(dataItem) {
    return dataItem.value[subjectName];
  };
}

chart
  .width(768)
  .height(480)
  .dimension(XDimension)
  .group(YDimension, "History", sel_stack('History'))
  .transitionDuration(500)
  .xUnits(dc.units.ordinal)
  .x(d3.scale.ordinal().domain(XDimension))
  .margins({left: 80, top: 20, right: 10, bottom: 20})
  .brushOn(false)
  .clipPadding(20)
  .title(function(d) {
  return d.key + '[' + this.layer + ']: ' + d.value[this.layer];
}).renderLabel(true);

chart.legend(dc.legend());

dc.override(chart, 'legendables', function() {
  var items = chart._legendables();
  return items.reverse();
});

for(var i = 0; i < subjects.length - 1; ++i) {
  chart.stack(
    YDimension,
    subjects[i],
    sel_stack(subjects[i])
  );
}

chart.render();
.dc-chart path.dc-symbol, .dc-legend g.dc-legend-item.fadeout {
  fill-opacity: 0.5;
  stroke-opacity: 0.5; }

div.dc-chart {
  float: left; }

.dc-chart rect.bar {
  stroke: none;
  cursor: pointer; }
  .dc-chart rect.bar:hover {
    fill-opacity: .5; }

.dc-chart rect.deselected {
  stroke: none;
  fill: #ccc; }

.dc-chart .pie-slice {
  fill: #fff;
  font-size: 12px;
  cursor: pointer; }
  .dc-chart .pie-slice.external {
    fill: #000; }
  .dc-chart .pie-slice :hover, .dc-chart .pie-slice.highlight {
    fill-opacity: .8; }

.dc-chart .pie-path {
  fill: none;
  stroke-width: 2px;
  stroke: #000;
  opacity: 0.4; }

.dc-chart .selected path, .dc-chart .selected circle {
  stroke-width: 3;
  stroke: #ccc;
  fill-opacity: 1; }

.dc-chart .deselected path, .dc-chart .deselected circle {
  stroke: none;
  fill-opacity: .5;
  fill: #ccc; }

.dc-chart .axis path, .dc-chart .axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges; }

.dc-chart .axis text {
  font: 10px sans-serif; }

.dc-chart .grid-line, .dc-chart .axis .grid-line, .dc-chart .grid-line line, .dc-chart .axis .grid-line line {
  fill: none;
  stroke: #ccc;
  opacity: .5;
  shape-rendering: crispEdges; }

.dc-chart .brush rect.background {
  z-index: -999; }

.dc-chart .brush rect.extent {
  fill: #4682b4;
  fill-opacity: .125; }

.dc-chart .brush .resize path {
  fill: #eee;
  stroke: #666; }

.dc-chart path.line {
  fill: none;
  stroke-width: 1.5px; }

.dc-chart path.area {
  fill-opacity: .3;
  stroke: none; }

.dc-chart path.highlight {
  stroke-width: 3;
  fill-opacity: 1;
  stroke-opacity: 1; }

.dc-chart g.state {
  cursor: pointer; }
  .dc-chart g.state :hover {
    fill-opacity: .8; }
  .dc-chart g.state path {
    stroke: #fff; }

.dc-chart g.deselected path {
  fill: #808080; }

.dc-chart g.deselected text {
  display: none; }

.dc-chart g.row rect {
  fill-opacity: 0.8;
  cursor: pointer; }
  .dc-chart g.row rect:hover {
    fill-opacity: 0.6; }

.dc-chart g.row text {
  fill: #fff;
  font-size: 12px;
  cursor: pointer; }

.dc-chart g.dc-tooltip path {
  fill: none;
  stroke: #808080;
  stroke-opacity: .8; }

.dc-chart g.county path {
  stroke: #fff;
  fill: none; }

.dc-chart g.debug rect {
  fill: #00f;
  fill-opacity: .2; }

.dc-chart g.axis text {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  pointer-events: none; }

.dc-chart .node {
  font-size: 0.7em;
  cursor: pointer; }
  .dc-chart .node :hover {
    fill-opacity: .8; }

.dc-chart .bubble {
  stroke: none;
  fill-opacity: 0.6; }

.dc-chart .highlight {
  fill-opacity: 1;
  stroke-opacity: 1; }

.dc-chart .fadeout {
  fill-opacity: 0.2;
  stroke-opacity: 0.2; }

.dc-chart .box text {
  font: 10px sans-serif;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  pointer-events: none; }

.dc-chart .box line, .dc-chart .box circle {
  fill: #fff; }

.dc-chart .box rect, .dc-chart .box line, .dc-chart .box circle {
  stroke: #000;
  stroke-width: 1.5px; }

.dc-chart .box .center {
  stroke-dasharray: 3, 3; }

.dc-chart .box .outlier {
  fill: none;
  stroke: #ccc; }

.dc-chart .box.deselected {
  opacity: 0.5; }
  .dc-chart .box.deselected .box {
    fill: #ccc; }

.dc-chart .symbol {
  stroke: none; }

.dc-chart .heatmap .box-group.deselected rect {
  stroke: none;
  fill-opacity: 0.5;
  fill: #ccc; }

.dc-chart .heatmap g.axis text {
  pointer-events: all;
  cursor: pointer; }

.dc-chart .empty-chart .pie-slice {
  cursor: default; }
  .dc-chart .empty-chart .pie-slice path {
    fill: #fee;
    cursor: default; }

.dc-chart circle.dot {
  stroke: none; }

.dc-data-count {
  float: right;
  margin-top: 15px;
  margin-right: 15px; }
  .dc-data-count .filter-count, .dc-data-count .total-count {
    color: #3182bd;
    font-weight: bold; }

.dc-legend {
  font-size: 11px; }
  .dc-legend .dc-legend-item {
    cursor: pointer; }

.dc-hard .number-display {
  float: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>
<script src="https://rawgithub.com/NickQiZhu/dc.js/master/web/js/crossfilter.js"></script>
<script src="https://cdnjs.site44.com/dc3.js"></script>
<script src="https://d3js.org/d3.v3.min.js"></script>
<body>
    <div id='test'></div>
</body>