I have a barchart made with NVD3
that shows datas with a huge gap between min value and max value.
This makes the chart not really nice/usefull.
Example :
Y value are between 4,000 and 60,000 then some value are near 3m.
I would like to have an Y Axis value increasing logarithmically, that show something like this (see the y Axis):
I tried to change yAxis scale, yAxis Domain, but didn't find any working solution
(FYI: I use nvd3 through angularJs directives)
This will work for you
chart.y(function(d) { return d.value>0?Math.log10(d.value+1):0 })
chart.yAxis.tickFormat(function(d){return (Math.pow(10,d)-1).toFixed(2)})
Works only for positive values
The root of the issue is that barcharts in nvd3 start at 0, and log(0) == Infinity.
Unfortunately there is a particular line in nvd3 that uses y(0) when calculating the height of the bar for your chart. When y(0) evaluates to Infinity things break. Furthermore, nvd3 is currently undergoing a refactor so, they aren't taking any pull requests for the old code base.
Here is what worked for me. It's not a general soltuion, but I couldn't even find this level of info online so I'm posting it here.
In this case I'm using a Line plus Bar Chart, this may not work for other bar charts, but hopefully it gives you and idea of what needs to be done.
First, make sure your chart is setup properly.
yourChart.bars.yScale(d3.scale.log());
yourChart.bars.forceY([1]); //Make sure y axis starts at 1 not 0
yourChart.y1Axis.tickValues([1, 10, 100]); //Continue pattern for more ticks
now in nvd3.js around line 1600 (in nvd3 1.8 line number is 5605) you should see:
bars.transition()
.attr('y', function(d,i) {
var rval = getY(d,i) < 0 ?
y(0) :
y(0) - y(getY(d,i)) < 1 ?
y(0) - 1 :
y(getY(d,i));
return nv.utils.NaNtoZero(rval);
})
.attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(1)),1)) });
In the very last statement:
.attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(0)),1)) });
You need to replace y(0) with y(1) which will give you this:
.attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(1)),1)) });
If this doesn't work, look for other cases where nvd3 sets up bars.transition() and calculates the height. You may need to fix up other cases where 0 is passed to y().
Hope this helps.