Skip to content Skip to sidebar Skip to footer

Matplotlib: Secondary Axis With Values Mapped From Primary Axis

I have a graph showing x4 vs y: y is the log of some other variable, say q (i.e. y = log(q) ) the value of q is what the layperson will understand when reading this graph. I want

Solution 1:

My suggestion here would be to use a twin axes and share it will the original axes to fix the tick positions. You may then use a FuncFormatter to give the ticks the correct labels. The advantage of this is that you do not need to fix the limits of the plot a priori and can freely zoom and pan inside the plot.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter


f = lambda q: np.log(q)
finv = lambda x: np.exp(x)

x = np.random.rand(100,)
y = f(np.random.rand(100,))


fig, ax = plt.subplots()
ax2 = ax.twinx()
ax.get_shared_y_axes().join(ax,ax2)

ax.scatter(x, y)

ax2.yaxis.set_major_formatter(FuncFormatter(lambda x,pos: f"{finv(x):.2f}"))
plt.show()

enter image description here

Solution 2:

You can use a twin axis. The idea is following:

  • Create a twin axis and plot the same data on both the axis. This will make sure that the tick positions are axis limits are same on both y-axis.
  • Get the tick labels which are strings, convert them to integers and take their exponent using np.exp() rounding them up to 2 decimal places.
  • Assign the new labels to the right hand side y-axis
  • You also need to mae sure both axes have the same number of ticks and same extents as suggested by @ImportanceOfBeingEarnest in the comments below

import numpy as np; np.random.seed(123)
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

q = np.random.rand(100,)
y = np.log(q)
x4 = np.random.rand(100,)

ax.scatter(x4, y)
ax.set_xlabel('x4', fontsize=16)
ax.set_ylabel('y', fontsize=16)

ax2 = ax.twinx()
ax2.scatter(x4, y)

ax2.set_yticks(ax.get_yticks())
ax2.set_ylim(ax.get_ylim())
fig.canvas.draw()

labels = [int(i.get_text()[1:-1]) for i in ax2.get_yticklabels()]
labels_new = [np.round(np.exp(i), 2) for i in labels]

ax2.set_yticklabels(labels_new);
ax2.set_ylabel('q', fontsize=16)
plt.show()

enter image description here

Post a Comment for "Matplotlib: Secondary Axis With Values Mapped From Primary Axis"