3

how can a logscale be set for values that are already logged but too large to be exponentiated back to linear scale? example:

import matplotlib.pylab as plt
import numpy as np

def f_returns_verylarge_logs():
    # some computation here that returns very small numbers on a log scale
    # (meaning large negative numbers in log units)
    log10_y = [3000, 3100, 3200]
    return log10_y

ax1 = plt.subplot(2, 1, 1)
x = [1, 2, 3]
# y values are small, so it is no problem to keep them
# around in LINEAR scale
y = [50, 100, 200]
plt.plot(x, y)
plt.xlabel("x")
plt.ylabel("y")
ax1.set(yscale="log")
ax2 = plt.subplot(2, 1, 2)
x = [1, 2, 3]
log_y = f_returns_verylarge_logs()
y = np.power(10., log_y) 
plt.plot(x, y)
plt.xlabel("x")
plt.ylabel("y")
ax2.set(yscale="log")
plt.show()

this gives overflow error:

RuntimeWarning: overflow encountered in power
  y = np.power(10., log_y)

the goal is to make the bottom plot work and look (in terms of yticks/labels) like the top without unlogging log_y since it causes overflow.

a bad solution is to scale down the log values and then unlog them as in:

plt.figure()
scaled_log_y = np.array(log_y) / 100.
scaled_unlog_y = np.power(10., scaled_log_y)
plt.plot(x, scaled_unlog_y)
plt.gca().set(yscale="log")
plt.ylabel("y (units are wrong)")
plt.xlabel("x")
plt.show()

but this gives wrong units: for 3000, it says 10^30 instead of 10^3000.

7
  • 2
    Why do you want to turn on the logarithmic scale if the values are already logarithmic? Commented Jun 13, 2019 at 13:27
  • @mkrieger1: to get all the nice axis formatting - labels like 10^x, the minor ticks that come with that, etc. Commented Jun 13, 2019 at 13:31
  • It would be super helpful if the reader is spared of doing all the math and comprehending what you mean, and you include some example of what the final figure should look like, providing a sample case of the transformation/rescaling you are talking about. Commented Jun 13, 2019 at 13:49
  • Ticks and scale are two different pair of shoes. But to me it doesn't make sense to have logarithmically scaled ticks on a linear axis. Hence I think this question needs a bit more explanation about the problem and a clear description of the desired outcome. Pay attention not to make this an xyproblem. Commented Jun 13, 2019 at 14:23
  • @ImportanceOfBeingErnest: see edits. the yaxis here is not linear. Commented Jun 13, 2019 at 14:41

1 Answer 1

2

Possibly you want something like the following, where simply each tick at position n is labelled by "10^n".

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker

x = [1, 2, 3]
y1 = [50, 100, 200]
y2 = [3000, 3100, 3200]

ax1 = plt.subplot(2, 1, 1)
ax1.plot(x, y1)
ax1.set_xlabel("x")
ax1.set_ylabel("y")
ax1.set(yscale="log")

ax2 = plt.subplot(2, 1, 2)

ax2.plot(x, y2)
ax2.set_xlabel("x")
ax2.set_ylabel("y")
ax2.yaxis.set_major_formatter(mticker.FuncFormatter(lambda x,_: f"$10^{{{int(x)}}}$"))

plt.show()

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

yes, exactly, but I also want the minor ticks with logspacing like you have in the top subplot
@user248237, For adding minor ticks, try this: stackoverflow.com/a/64840431/1265409

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.