thekkm13 - 3 months ago 35x
Javascript Question

# d3 js axis Percentage Values with decimals

I'm using d3 to create a graph - (still learning both of those). I'd like my Y-axis to display values in percentages. The min and max values on the Y-axis are allocated dynamically, so the axis scale could sometimes be

`25% to 38%`
or sometimes even
`13% to 16%`
.

When there is a relatively larger range such as
`25% to 28%`
, I'm fine with the numbers appearing as they are, i.e.
`25%, 28%, 31% ....`

However, for a really small range, I notice it appears as
`13%, 14%, 14%, 15%, 15%,...`
(numbers repeating, probably because behind the scenes they might be something like say,
`14.2%`
and
`14.8%`
).
In such cases, I'd like the numbers to appear with 1 decimal place specified, such as
`13.5%`
.

I know I can specify

``````.tickFormat(d3.format(".1%"))
``````

and this gives me what I need in that case. The problem is when I have a larger scale, it essentially gives me
`25.0%, 28.0%, 31.0%,...`
and in this case, I'd like no decimal precision.

Is there a simple way I can handle each scenario? Any guidance would be most appreciated.

As mentioned in the comments, you could check if the range is big enough and add the decimal point format depending on that but that wouldn't be very clean. I suggest you pass your own function as the `tickFormat` that applies the format depending if the value has a decimal portion or not. Something like:

``````// defined your formatters somewhere above
var decimalFormatter = d3.format(".1");

myAxis.tickFormat(function(d) {
if (!Number.isInteger(d)) {
d = decimalFormatter(d); // add the decimal point for non-integers
}
return d + '%';
}
``````

Sample code:

``````// defined your formatters somewhere above
var decimalFormatter = d3.format(".1");

var tickFormat = function(d) {
if (!Number.isInteger(d)) {
d = decimalFormatter(d); // add the decimal point for non-integers
}
return d + '%';
};

console.log(tickFormat(12.5)); // 12.5%
console.log(tickFormat(14));   // 14%
console.log(tickFormat(15));   // 15%``````
``<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>``

Where you can adjust the function above in any specific way you might need. For example, if you are using strings instead of numbers, you will need to first convert to a number and then use `Number.isInteger` because it will always return `false` for a string.

Source (Stackoverflow)