Viju Viswan
Viju Viswan

Reputation: 52

Error on horizontal Bar chart using d3.js

I have created a horizontal bar chart using d3.js and every thing works fine if no identical columns values(here it is 'response' field) occurs.

eg: var data = [{ "answer": "Answer2", "response": 5, "total": 7, "color": "#ff4700" }, { "answer": "Answer3", "response": 5, "total": 7, "color": "#0ED5EE" }, { "answer": "Answer4", "response": 1, "total": 7, "color": "#31EE0E" }]; If we provide same value on 'response' field( say repeating 5) , the resultant bar count will be not matched as expected, otherwise it will draw perfectly. Can you please help me to sort out this issue. Thanks and regards

Upvotes: 2

Views: 77

Answers (2)

marcel-k
marcel-k

Reputation: 103

The y axis domain value must be unique for it to work properly.

So your response value is not unique and in theory your answer does not have to be unique either. Furthermore, using answer as domain and then getting the data by index seems dirty and may cause unexpected results when (re-)sorting the data.

To get unique values for your y domain you could add an unique id to each of your data objects e.g.:

var data = [{
  "uniqueId": 1,
  "answer": "Answer2",
  "response": 5,
  "total": 7,
  "color": "#ff4700"
},....]

y.domain(data.map(function(d) { return d.uniqueId; }));

And then add a tickFormat to the yAxis:

yAxis.tickFormat(function(id, i){         
  var d = data.find(function(d) { return d.uniqueId === id; });
  var percentage = parseFloat( (d.response/d.total) * 100).toFixed(1)
  return percentage + '%';
})

result: https://jsfiddle.net/rd8z5k32/1/

Alternatively you could just use the indexes of the data array as domain:

y.domain(d3.range(data.length));

yAxis.tickFormat(function(_d, i){      
  var d = data[i];
  var percentage = parseFloat( (d.response/d.total) * 100).toFixed(1)
  return percentage + '%';
})

Upvotes: 1

Cyril Cherian
Cyril Cherian

Reputation: 32327

For y domain give unique name in your case answer:

   .domain(data.map(function(d) {
     return d.answer;
   }));

Then for the y axis give tick format:

   .tickFormat(function(d, i){         
   var d = data[i];
   var percentage = parseFloat( (d.response/d.total) * 100).toFixed(1)
   return percentage + '%'; })

working code here

Upvotes: 2

Related Questions