10

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?

Community
  • 1
  • 1
user1318806
  • 785
  • 3
  • 9
  • 13
  • 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? – David Zwicker Feb 13 '14 at 09:33
  • possibly a typo in the last sentence? Title says log and linear but qu says two log scales – Bonlenfum Feb 13 '14 at 10:34

3 Answers3

11

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

Community
  • 1
  • 1
JP Maulion
  • 2,454
  • 1
  • 10
  • 13
  • 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 http://stackoverflow.com/help/self-answer – SiKing Dec 13 '16 at 17:20
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

cphlewis
  • 15,759
  • 4
  • 46
  • 55
  • 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. – user1318806 Feb 20 '14 at 08:36
  • 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.) – cphlewis Feb 20 '14 at 20:03
3

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

Community
  • 1
  • 1