plotly.js
plotly.js copied to clipboard
Bug report & feature request: Formatting numbers with natural language suffixes, k(ilo), M(illion), B(illion)
Plotly doesn't currently let me format numbers, e.g. in hover templates, in "human" or "business" form, by which I mean essentially SI representation but with the suffix replacements k->k(ilo) M->M(illion), G->B(illion), T->T(trillion),.... (by pure luck, this is really just one necessary replacement in the range I've listed).
The reason seems to be that plotly relies on d3-format, which claims to "format numbers for human consumption" but misses the one format non-technically trained humans can actually consume at ease.
However, oddly plotly does use the "human readable" form by default for the X and Y columns in default hover displays, even when they're included in the hover templates manually as %{y}
, but not for custom data included via %{customdata[0]}
(see the MWE below). This in some sense makes this a bug: You want to include two columns of data in the same way, using the same format specifier, but you get different results.
Instead of waiting on d3, I would like to make this feature request: I believe plotly should default for custom data to the same formatting it uses by default elsewhere (including axes labels), unless a format specifier is explicitly listed, thus increasing consistency.
Example: Despite using text=y
and hovertemplate ='%{y}<br>%{text}'
, I get different representations:
import plotly.graph_objects as go
y = [2, 100000, 2000000, 2000000000]
fig = go.Figure(go.Scatter(
x = [1,2,3,4],
y = y,
text = y,
hovertemplate ='%{y}<br>%{text}'
))
fig.show()
Similar requests elsewhere: https://github.com/plotly/plotly.py/issues/1222
https://stackoverflow.com/questions/68005050/b-billions-instead-of-g-giga-in-python-plotly-customdata-si-prefix-d3
https://stackoverflow.com/questions/17037023/how-to-get-localizable-or-customizable-si-codes-with-d3-format
https://community.plotly.com/t/custom-si-unit-prefixes/29739/4
https://stackoverflow.com/questions/40774677/d3-formatting-tick-value-to-show-b-billion-instead-of-g-giga
https://github.com/d3/d3/issues/2241
https://stackoverflow.com/questions/64313173/how-to-hover-number-formatting-to-k-or-m-accordingly-in-r-plotly-pie-charts-and
https://github.com/d3/d3-format/issues/71
https://github.com/d3/d3-format/pull/81
https://github.com/d3/d3-format/pull/96
One option is to selectively override d3.format in your application, adding rules your customer base would prefer.
The below code overrides d3.format
to define a whimsical custom format , and fall back to standard d3.format
otherwise
var _d3format = d3.format
d3.format = function(fmt) {
var getMagnitude = function(v) { return Math.floor(Math.log10(v)/3)}
var prefixes = ['do','di','re','ri','mi','fa','fi','so','si','la','li','ti','do']
var getPrefix = function(mag) { return prefixes[mag]}
if (fmt == 'solfege') {
return function(val) {
var str = _d3format('s')(val)
var mag = getMagnitude(val)
if (mag>4 && mag<4+prefixes.length) {
var base = str.slice(0,3)
var pre = getPrefix(mag-4)
return base + ' '+ pre + "zillions"
}
else return _d3format("0.3s")(val)
}
}
else return _d3format(fmt)
}
e.g. d3.format('solfege')(3403940323489323092394829839240)
yields "340 fizillions"
Of course, be careful if your code is to be embedded in other code, where polluting d3
might cause issues with other libraries