How to manually set axis offset with custom tick labels?

53 Views Asked by At

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

2

There are 2 best solutions below

0
Ratislaus On BEST ANSWER

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

0
Axel Donath On

You can just manually place a label using ax.text():

import numpy as np
import matplotlib.pyplot as plt

s = 10000000

x, y = np.array([1, 1, 2, 3, 5]), s * np.array([2, 3, 5, 7])
z = np.random.rand(y.size, x.size)

ax = plt.subplot()
ax.imshow(z)
ax.set_yticks(np.arange(len(y)))
ax.set_xticks(np.arange(len(x)))
ax.set_yticklabels(y / s)
ax.set_xticklabels(x)

# the position here is given in pixel coordinates
ax.text(-0.5, -0.55, f"{s:.0e}")

plt.show()

I hope this helps!