Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to produce an exponentially scaled axis?

Consider the following code:

from numpy import log2
import matplotlib.pyplot as plt

xdata = [log2(x)*(10/log2(10)) for x in range(1,11)]
ydata = range(10)
plt.plot(xdata, ydata)
plt.show()

This produces the following plot: The plot I do not want My question is, how can I modify this, so that the plot, with the exact same data as input, appears as a straight line? This basically requires scaling the x-axis appropriately, but I cannot figure how to do this. The reason for doing this is that I am displaying a function that changes very little at the beginning, but starts to fluctuate more towards the end of the valid interval, so I want to have a higher horizontal resolution towards the end. If anyone can propose an alternative solution to my approach, feel free to do so!

like image 402
Björn Pollex Avatar asked Feb 04 '11 15:02

Björn Pollex


People also ask

How do I change the Y axis range in Matplotlib?

To change the range of X and Y axes, we can use xlim() and ylim() methods.


Video Answer


2 Answers

Here is how it is done. A good example to follow. You just subclass the ScaleBase class.

Here's your transform. It's not too complicated when you whittle out all the custom formatters and stuff. Just a little verbose.

from numpy import log2
import matplotlib.pyplot as plt

from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms

class CustomScale(mscale.ScaleBase):
    name = 'custom'

    def __init__(self, axis, **kwargs):
        mscale.ScaleBase.__init__(self)
        self.thresh = None #thresh

    def get_transform(self):
        return self.CustomTransform(self.thresh)

    def set_default_locators_and_formatters(self, axis):
        pass

    class CustomTransform(mtransforms.Transform):
        input_dims = 1
        output_dims = 1
        is_separable = True

        def __init__(self, thresh):
            mtransforms.Transform.__init__(self)
            self.thresh = thresh

        def transform_non_affine(self, a):
            return 10**(a/10)

        def inverted(self):
            return CustomScale.InvertedCustomTransform(self.thresh)

    class InvertedCustomTransform(mtransforms.Transform):
        input_dims = 1
        output_dims = 1
        is_separable = True

        def __init__(self, thresh):
            mtransforms.Transform.__init__(self)
            self.thresh = thresh

        def transform_non_affine(self, a):
            return log2(a)*(10/log2(10))

        def inverted(self):
            return CustomScale.CustomTransform(self.thresh)


mscale.register_scale(CustomScale)

xdata = [log2(x)*(10/log2(10)) for x in range(1,11)]
ydata = range(10)
plt.plot(xdata, ydata)

plt.gca().set_xscale('custom')
plt.show()
like image 173
Paul Avatar answered Oct 22 '22 04:10

Paul


The easiest way is to use semilogy

from numpy import log2
import matplotlib.pyplot as plt

xdata = log2(range(1,11)) * (10/log2(10))
ydata = range(10)
plt.semilogy(xdata, ydata)
plt.show()

enter image description here

like image 43
Joe Kington Avatar answered Oct 22 '22 04:10

Joe Kington