I want to have ticks on the y-axis formatted the following way:
20 000
)2.0
with x10^6
above the axis).Now, I can achieve both of these functionalities seperataly.
matplotlib.ticker.FuncFormatter(lambda x, p: format(x, ',').replace(',', ' '))
replaces thousands separator with space.
formatter = matplotlib.ticker.ScalarFormatter()
formatter.set_powerlimits((-4, 6))
gives scientific notation for 1M+.
I guess I have to set a ScalarFormatter and slightly change one of its functions, or I have to write above the y-axis with the FuncFormatter. However, I could not find how to do that.
I slightly came closer to my goal. By using format(x, ',.6g').replace(',', ' ')
I at least have the desired number formats.
Nevertheless, I'd prefer to have the exponential notation above the axis, and for all of my ticks, if the largest grows too large...
In principle you could just set_useLocale(True)
for the scalar formatter and use a modified locale. ScalarFormatter doesn't, however, use groupings (see source), so we must derive our own ScalarFormatter and set grouping=True
).
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter
import locale
fig, (ax1, ax2) = plt.subplots(ncols=2)
ax1.set_ylim(1, 10_000)
ax2.set_ylim(1, 10_000_000)
class MyScalarFormatter(ScalarFormatter):
def __call__(self, x, pos=None):
if len(self.locs) == 0:
return ''
else:
xp = (x - self.offset) / (10. ** self.orderOfMagnitude)
if abs(xp) < 1e-8:
xp = 0
if self._useLocale:
s = locale.format_string(self.format, (xp,), grouping=True)
else:
s = self.format % xp
return self.fix_minus(s)
sf = MyScalarFormatter(useLocale=True)
locale._override_localeconv = {'thousands_sep': ' ', 'grouping': [3,0]}
ax1.yaxis.set_major_formatter(sf)
ax2.yaxis.set_major_formatter(sf)
plt.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With