11

The example here What is the difference between 'log' and 'symlog'? nicely shows how a linear scale at the origin can be used with a log scale elsewhere. I want to go the other way around. I want to have a a log scale from 1-100 and then a linear! scale from 100-1000. What are my options? Like the figure above This attempt did not work

    import matplotlib.pyplot as plt
    plt.figure()
    plt.errorbar(x, y, yerr=yerrors)
    plt.xscale('symlog', linthreshx= (100,1000))

The problem seems to be that linthreshx is defined to take the range (-x,x). So if x if 5 we would get a linear scale on (-5,5). One is confined to the origin. I thought simply choosing a different range should work but it does not. Any ideas?

2
  • 1
    Why don't you just have a log scale from 1 to 1000? I don't see what you're aiming at? Can you provide a sketch of what you're trying to achieve? Commented Feb 13, 2014 at 9:33
  • possibly a typo in the last sentence? Title says log and linear but qu says two log scales Commented Feb 13, 2014 at 10:34

3 Answers 3

13

From the response of user1318806 to cphlewis:

Thank you. Actually I wanted a combination of log+linear on the x axis not y. But I assume your code should be easily adaptable.

Hello! If you wanted a combination of log+linear on the x-axis (patterned from the code of Duncan Watts and CubeJockey):

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np

# Numbers from -50 to 50, with 0.1 as step
xdomain = np.arange(-50,50, 0.1)

axMain = plt.subplot(111)
axMain.plot(np.sin(xdomain), xdomain)
axMain.set_xscale('linear')
axMain.set_xlim((0.5, 1.5))
axMain.spines['left'].set_visible(False)
axMain.yaxis.set_ticks_position('right')
axMain.yaxis.set_visible(False)


divider = make_axes_locatable(axMain)
axLin = divider.append_axes("left", size=2.0, pad=0, sharey=axMain)
axLin.set_xscale('log')
axLin.set_xlim((0.01, 0.5))
axLin.plot(np.sin(xdomain), xdomain)
axLin.spines['right'].set_visible(False)
axLin.yaxis.set_ticks_position('left')
plt.setp(axLin.get_xticklabels(), visible=True)

plt.title('Linear right, log left')

The code above yields: Answer1

(MISCELLANEOUS) Here's a very minor fix for the title and the absence of tick marks on the right side:

# Fix for: title + no tick marks on the right side of the plot
ax2 = axLin.twinx()
ax2.spines['left'].set_visible(False)
ax2.tick_params(axis='y',which='both',labelright='off')

Adding these lines will give you this: Answer2

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

1 Comment

Welcome to SO. In this case - answering a question that was asked in a comment - it is actually perfectly acceptable for you to ask a brand new question on SO, possibly linking back to the source, and then answer your own question. See stackoverflow.com/help/self-answer
8

I assume you want linear near the origin, log farther -- since `symlog' does it the other way around -- I couldn't come up with data that looked good like this, but you can put it together with the axes_grid:

# linear and log axes for the same plot?
# starting with the histogram example from 
# http://matplotlib.org/mpl_toolkits/axes_grid/users/overview.html
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np

# Numbers from -50 to 50, with 0.1 as step
xdomain = np.arange(-50,50, 0.1)

axMain = plt.subplot(111)
axMain.plot(xdomain, np.sin(xdomain))
axMain.set_yscale('log')
axMain.set_ylim((0.01, 0.5))
divider = make_axes_locatable(axMain)
axLin = divider.append_axes("top", size=2.0, pad=0.02, sharex=axMain)
axLin.plot(xdomain, np.sin(xdomain))

axLin.set_xscale('linear')
axLin.set_ylim((0.5, 1.5))
plt.title('Linear above, log below')

plt.show()

enter image description here

2 Comments

Thank you. Actually I wanted a combination of log+linear on the x axis not y. But I assume your code should be easily adaptable. I will try it soon. I want to do what symlog does but with the order reversed. symlog does linear+log on the x-axis. I want log+linear on the x-axis.
As long as the shared axis uses the same scale, you should be good; and yes, make_axes_locatable can add an axis in either direction. (Or both.)
4

This solution makes an addition to cphlewis's answer so that there is a smooth transition, and the plot appears to have consistent tick markers. My change adds these three lines:

axLin.spines['bottom'].set_visible(False)

axLin.xaxis.set_ticks_position('top')

plt.setp(axLin.get_xticklabels(), visible=False)

In total, the code is

# linear and log axes for the same plot?
# starting with the histogram example from 
# http://matplotlib.org/mpl_toolkits/axes_grid/users/overview.html
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np

# Numbers from -50 to 50, with 0.1 as step
xdomain = np.arange(-50,50, 0.1)

axMain = plt.subplot(111)
axMain.plot(xdomain, np.sin(xdomain))
axMain.set_yscale('log')
axMain.set_ylim((0.01, 0.5))
axMain.spines['top'].set_visible(False)
axMain.xaxis.set_ticks_position('bottom')

divider = make_axes_locatable(axMain)
axLin = divider.append_axes("top", size=2.0, pad=0, sharex=axMain)
axLin.plot(xdomain, np.sin(xdomain))
axLin.set_xscale('linear')
axLin.set_ylim((0.5, 1.5))

# Removes bottom axis line
axLin.spines['bottom'].set_visible(False)
axLin.xaxis.set_ticks_position('top')
plt.setp(axLin.get_xticklabels(), visible=False)

plt.title('Linear above, log below')

plt.show()

enter image description here

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.