Add scale.tickPrecision to query appropriate format percision. #912

Closed
ezyang opened this Issue Nov 19, 2012 · 4 comments

3 participants

@ezyang

Suppose that I have an axis for a quantity that is percentages. The obvious way to implement this is axis.tickFormat(d3.format('%')). However, this number will have its precision clipped to the units place, so if you have very small quantities you'll see '1% 1% 1% 1% 2% 2%..." So, what we'd like is to be able to ask for a custom format, but at the same time get the precision computed for us. (Maybe this would be a new argument for scale.tickFormat)

@jasondavies
D3 member

You can set the precision using . e.g. .2% will give you two decimal places of precision.

See the documentation for more options.

@mbostock
D3 member

@jasondavies Yeah, but he was asking for the precision to be computed automatically by the scale.

You can get pretty close by using d3.format("p") rather than d3.format("%"). However, this might exhibit floating point errors in certain cases.

One fix might be a tickPrecision method:

scale.tickPrecision = function(m) {
  return Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01));
};

Perhaps a more useful though less flexible fix is to add a format type to tickFormat (pseudo code):

scale.tickFormat = function(m, type) {
  if (arguments.length < 2) type = "f";
  return d3.format(",." + precision + type);
};

This approach would work fairly well with d3.svg.axis since you can pass-through arguments via axis.ticks(10, "%"). But it's a bit limiting since you can't override other parts of the format. You'd need some way to specify a full format, but with an implied precision that can be overridden later. So I think it's probably simplest to just expose tickPrecision.

@jasondavies
D3 member

Ah, sorry about that. The tickPrecision idea sounds good.

@mbostock mbostock added a commit that referenced this issue Mar 12, 2013
@mbostock mbostock Automatic precision for custom tick formats.
You can now pass a format specifier to scale.tickFormat (for linear, pow and
identity scales). If the format specifier doesn't have a defined precision, the
precision will be set automatically by the scale, returning the appropriate
format. This provides a convenient, declarative way of specifying a format whose
precision will be automatically set by the scale.

This works with axes, too! For example, `axis.ticks(10, "%")` will now use a
percentage format rather than the default format, while still computing the
appropriate precision.

This commit also includes a fix to make d3.format more robust when unreasonable
precisions are specified. Rather than throwing an error, the nearest reasonable
value is used instead.

Fixes #912.
d0441e6
@mbostock
D3 member

Staged in #1120.

@mbostock mbostock closed this Mar 12, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment