pythonmatplotlibscalelogarithm

What is the difference between 'log' and 'symlog'?


In matplotlib, I can set the axis scaling using either pyplot.xscale() or Axes.set_xscale(). Both functions accept three different scales: 'linear' | 'log' | 'symlog'.

What is the difference between 'log' and 'symlog'? In a simple test I did, they both looked exactly the same.

I know the documentation says they accept different parameters, but I still don't understand the difference between them. Can someone please explain it? The answer will be the best if it has some sample code and graphics! (also: where does the name 'symlog' come from?)


Solution

  • I finally found some time to do some experiments in order to understand the difference between them. Here's what I discovered:

    I think everything will get a lot easier to understand with graphics and examples, so let's try them:

    import numpy
    from matplotlib import pyplot
    
    # Enable interactive mode
    pyplot.ion()
    
    # Draw the grid lines
    pyplot.grid(True)
    
    # Numbers from -50 to 50, with 0.1 as step
    xdomain = numpy.arange(-50,50, 0.1)
    
    # Plots a simple linear function 'f(x) = x'
    pyplot.plot(xdomain, xdomain)
    # Plots 'sin(x)'
    pyplot.plot(xdomain, numpy.sin(xdomain))
    
    # 'linear' is the default mode, so this next line is redundant:
    pyplot.xscale('linear')
    

    A graph using 'linear' scaling

    # How to treat negative values?
    # 'mask' will treat negative values as invalid
    # 'mask' is the default, so the next two lines are equivalent
    pyplot.xscale('log')
    pyplot.xscale('log', nonposx='mask')
    

    A graph using 'log' scaling and nonposx='mask'

    # 'clip' will map all negative values a very small positive one
    pyplot.xscale('log', nonposx='clip')
    

    A graph using 'log' scaling and nonposx='clip'

    # 'symlog' scaling, however, handles negative values nicely
    pyplot.xscale('symlog')
    

    A graph using 'symlog' scaling

    # And you can even set a linear range around zero
    pyplot.xscale('symlog', linthreshx=20)
    

    A graph using 'symlog' scaling, but linear within (-20,20)

    Just for completeness, I've used the following code to save each figure:

    # Default dpi is 80
    pyplot.savefig('matplotlib_xscale_linear.png', dpi=50, bbox_inches='tight')
    

    Remember you can change the figure size using:

    fig = pyplot.gcf()
    fig.set_size_inches([4., 3.])
    # Default size: [8., 6.]
    

    (If you are unsure about me answering my own question, read this)