6

Possible Duplicate:
How to remove relative shift in matplotlib axis

I'm plotting numbers with five digits (210.10, 210.25, 211.35, etc) against dates and I'd like to have the y-axis ticks show all digits ('214.20' rather than '0.20 + 2.14e2') and have not been able to figure this out. I've attempted to set the ticklabel format to plain, but it appears to have no effect.

plt.ticklabel_format(style='plain', axis='y')

Any hints on the obvious I'm missing?

Zephyr
  • 11,891
  • 53
  • 45
  • 80
kitsu3
  • 63
  • 1
  • 1
  • 3
  • http://stackoverflow.com/questions/11855363/how-to-remove-relative-shift-in-matplotlib-axis/11858063#11858063 possible duplicate. – tacaswell Jan 21 '13 at 17:21

2 Answers2

14

The axis numbers are defined according to a given Formatter. Unfortunately (AFAIK), matplotlib does not expose a way to control the threshold to go from the numbers to a smaller number + offset. A brute force approach would be setting all the xtick strings:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(100, 100.1, 100)
y = np.arange(100)

fig = plt.figure()
plt.plot(x, y)
plt.show()  # original problem

enter image description here

# setting the xticks to have 3 decimal places
xx, locs = plt.xticks()
ll = ['%.3f' % a for a in xx]
plt.xticks(xx, ll)
plt.show()

enter image description here

This is actually the same as setting a FixedFormatter with the strings:

from matplotlib.ticker import FixedFormatter
plt.gca().xaxis.set_major_formatter(FixedFormatter(ll))

However, the problem of this approach is that the labels are fixed. If you want to resize/pan the plot, you have to start over again. A more flexible approach is using the FuncFormatter:

def form3(x, pos):
    """ This function returns a string with 3 decimal places, given the input x"""
    return '%.3f' % x

from matplotlib.ticker import FuncFormatter
formatter = FuncFormatter(form3)
gca().xaxis.set_major_formatter(FuncFormatter(formatter))

And now you can move the plot and still maintain the same precision. But sometimes this is not ideal. One doesn't always want a fixed precision. One would like to preserve the default Formatter behaviour, just increase the threshold to when it starts adding an offset. There is no exposed mechanism for this, so what I end up doing is to change the source code. It's pretty easy, just change one character in one line in ticker.py. If you look at that github version, it's on line 497:

if np.absolute(ave_oom - range_oom) >= 3:  # four sig-figs

I usually change it to:

if np.absolute(ave_oom - range_oom) >= 5:  # four sig-figs

and find that it works fine for my uses. Change that file in your matplotlib installation, and then remember to restart python before it takes effect.

tiago
  • 22,602
  • 12
  • 72
  • 88
7

You can also just turn the offset off: (almost exact copy of How to remove relative shift in matplotlib axis)

import matlplotlib is plt

plt.plot([1000, 1001, 1002], [1, 2, 3])
plt.gca().get_xaxis().get_major_formatter().set_useOffset(False)
plt.draw()

This grabs the current axes, gets the x-axis axis object and then the major formatter object and sets useOffset to false (doc).

Community
  • 1
  • 1
tacaswell
  • 84,579
  • 22
  • 210
  • 199
  • The problem of turning the offset off is that when you have large numbers they overlap each other. That's why I prefer to have a larger threshold to use the offset. – tiago Jan 21 '13 at 18:50
  • @tiago You should sumbit a feature request to `matplotlib` to make that threshold settable via rcParam. – tacaswell Jan 21 '13 at 19:02
  • I know. But I've been too lazy for quite a few matplotlib versions... – tiago Jan 21 '13 at 19:05