Reputation: 173
I am creating my custom descrete bar chart using nvd3.js and i need to pass 2 arrays of values instead of one. this is default data array from nvd3 example of decrete bar chart:
historicalBarChart = [
{
key: "Cumulative Return",
values: [
{
"label": "May",
"value": 32,
},
{
"label": "Jun",
"value": 22
},
{
"label": "Jul",
"value": 37
},
{
"label": "Aug",
"value": 42
},
{
"label": "Sep",
"value": 18
},
{
"label": "Oct",
"value": 14
},
{
"label": "Nov",
"value": 34
},
{
"label": "Dec",
"value": 5
}
]
}
];
and here is the picture of the chart http://www.dodaj.rs/f/47/BU/3mMgYntS/screen-shot-2013-12-21-a.png and this is how mine should look like:
when i add second array of data my bar looks like on the this image http://www.dodaj.rs/f/k/MP/4yKWKm66/screen-shot-2013-12-21-a.png
as you can see on the second image bars got thiner and there is a space for 2 bars on each month, but they overlaps instead going one next to the other. I'v tried everything but i am new to nvd3 and i cant figure out how to make the bars not overlaps.
Upvotes: 1
Views: 1424
Reputation: 1933
Why are multiple values mapping to the same location in my chart?
The problem is the underlying scale that is being used within the NVD3 code. Ordinal scales in d3 map a corresponding value to its position within the chart. You must have unique data for each entry in the domain that you are using to map to a value if you want it to map two months to a different area. If any of the values in your domain are used again when they are passed to an ordinal function they will be mapped to the corresponding position that was mapped for the first value.
var domain= ["January","February",...,"December"];
var set1 = [{"Month":"January", "Value":2},{{"Month":"February", "Value":3}}];
var set2 = [{"Month":"January", "Value":6},{{"Month":"August", "Value":20}}];
var ordinalScale = d3.scale().ordinal().domain([domain]);
if (ordinalScale(set1[0].Month) == ordinalScale(set2[0].Month))
{
console.log("true")
}
This would print true if the code compiled.
Intuitively Understanding the Problem:
The problem you're facing is that you're using a one-to-one function. Think about it like this
Suppose you have a domain (x = 1..10). Define the function f(x) = x + 1
What happens if you put x in?
f(1) = 2
f(2) = 3
f(1) = 2
Notice how you have multiple occurrences of inputting the same x generated for the same input? That's supposed to happen because you defined f(x) to behave like that.
Solution:
A way that you can fix this is to use a different type of chart such as a grouped chart. Another way that you can fix this yourself is to generate a unique value for each piece of data to be your domain value such as a modification to the above data in the following.
var set1 = [{"Month":"January", "Value":2, "Serial":1},{{"Month":"February", "Value":3},"Serial":2}];
var set2 = [{"Month":"January", "Value":6,"Serial":3},{{"Month":"August", "Value":20, "Serial":4}}];
Using this would solve your problem but create a new one. Since you use your domain values to generate your labels you'll have the values display instead of the months. To fix this you could use a tick formatter to display the month instead of the serial number.
Upvotes: 2