Matplotlib log scale tick label number formatting
Solution 1:
Sure, just change the formatter.
For example, if we have this plot:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.axis([1, 10000, 1, 100000])
ax.loglog()
plt.show()
You could set the tick labels manually, but then the tick locations and labels would be fixed when you zoom/pan/etc. Therefore, it's best to change the formatter. By default, a logarithmic scale uses a LogFormatter
, which will format the values in scientific notation. To change the formatter to the default for linear axes (ScalarFormatter
) use e.g.
from matplotlib.ticker import ScalarFormatter
for axis in [ax.xaxis, ax.yaxis]:
axis.set_major_formatter(ScalarFormatter())
Solution 2:
I've found that using ScalarFormatter
is great if all your tick values are greater than or equal to 1. However, if you have a tick at a number <1
, the ScalarFormatter
prints the tick label as 0
.
We can use a FuncFormatter
from the matplotlib ticker
module to fix this issue. The simplest way to do this is with a lambda
function and the g
format specifier (thanks to @lenz in comments).
import matplotlib.ticker as ticker
ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y, _: '{:g}'.format(y)))
Note in my original answer I didn't use the g
format, instead I came up with this lambda
function with FuncFormatter
to set numbers >= 1
to their integer value, and numbers <1
to their decimal value, with the minimum number of decimal places required (i.e. 0.1, 0.01, 0.001
, etc). It assumes that you are only setting ticks on the base10
values.
import matplotlib.ticker as ticker
import numpy as np
ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda y,pos: ('{{:.{:1d}f}}'.format(int(np.maximum(-np.log10(y),0)))).format(y)))
For clarity, here's that lambda function written out in a more verbose, but also more understandable, way:
def myLogFormat(y,pos):
# Find the number of decimal places required
decimalplaces = int(np.maximum(-np.log10(y),0)) # =0 for numbers >=1
# Insert that number into a format string
formatstring = '{{:.{:1d}f}}'.format(decimalplaces)
# Return the formatted tick label
return formatstring.format(y)
ax.yaxis.set_major_formatter(ticker.FuncFormatter(myLogFormat))