Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib log scale tick label number formatting

With matplotlib when a log scale is specified for an axis, the default method of labeling that axis is with numbers that are 10 to a power eg. 10^6. Is there an easy way to change all of these labels to be their full numerical representation? eg. 1, 10, 100, etc.

Note that I do not know what the range of powers will be and want to support an arbitrary range (negatives included).

like image 601
Nat Dempkowski Avatar asked Feb 20 '14 21:02

Nat Dempkowski


People also ask

How do I change the number of ticks in Matplotlib?

Locator_params() function that lets us change the tightness and number of ticks in the plots. This is made for customizing the subplots in matplotlib, where we need the ticks packed a little tighter and limited. So, we can use this function to control the number of ticks on the plots.

How do I scale axis in Matplotlib?

Import matplotlib. To set x-axis scale to log, use xscale() function and pass log to it. To plot the graph, use plot() function. To set the limits of the x-axis, use xlim() function and pass max and min value to it. To set the limits of the y-axis, use ylim() function and pass top and bottom value to it.


2 Answers

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() 

enter image description here

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()) 

enter image description here

like image 66
Joe Kington Avatar answered Sep 22 '22 15:09

Joe Kington


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.

enter image description here

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))) 

enter image description here

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)) 
like image 28
tmdavison Avatar answered Sep 23 '22 15:09

tmdavison