Search code examples
pythonmatplotlibaxisxticks

How to manually set axis offset with custom tick labels?


Consider the plot below. Both axis have custom labels, to label the rows and columns in an imshow-plot. The problem now is that the y-axis has very large values. Ideally I'd like to manually set an axis-offset (i.e. on top of the axis somethng like 1e5) such that the ticks are only show a smaller number. How can I achieve that?

There was a solution provided here but it does not work in this case, as we do not have a ScalarFormatter due to the custom labels:

import numpy as np
import matplotlib.pyplot as plt
s = 10000000
x, y = [1, 1, 2, 3, 5], [2*s, 3*s, 5*s, 7*s]
x, y = np.meshgrid(x, y)
z = np.random.rand(x.shape[0], x.shape[1])
plt.imshow(z)
plt.gca().set_yticks(range(len(y[..., 0])))
plt.gca().set_xticks(range(len(x[0, ...])))
plt.gca().set_yticklabels(y[..., 0])
plt.gca().set_xticklabels(x[0, ...])
plt.show()

enter image description here


Solution

  • You could use matplotlib.ticker.FuncFormatter.set_offset_string() like this:

    import numpy as np
    import matplotlib.pyplot as plt
    s = 100000 # 1e+05
    x = [1, 1, 2, 3, 5]
    original_y = [20000000, 30000000, 50000000, 70000000]
    y = [oy / s for oy in original_y]
    x, y = np.meshgrid(x, y)
    z = np.random.rand(x.shape[0], x.shape[1])
    plt.imshow(z)
    plt.gca().set_yticks(range(len(y[..., 0])))
    plt.gca().set_xticks(range(len(x[0, ...])))
    plt.gca().set_yticklabels(y[..., 0])
    plt.gca().set_xticklabels(x[0, ...])
    plt.gca().yaxis.get_major_formatter().set_offset_string('{:.0e}'.format(s))
    plt.show()
    

    The result:

    enter image description here