Square root scale using matplotlib/python

后端 未结 4 1656
孤独总比滥情好
孤独总比滥情好 2020-12-21 05:55

I want to make a plot with square root scale using Python:

However, I have no idea how to make it. Matplotlib allows to make log scale but in this case I ne

相关标签:
4条回答
  • 2020-12-21 05:58

    You can make your own ScaleBase class to do this. I have modified the example from here (which made a square-scale, not a square-root-scale) for your purposes. Also, see the documentation here.

    Note that to do this properly, you should probably also create your own custom tick locator; I haven't done that here though; I just manually set the major and minor ticks using ax.set_yticks().

    import matplotlib.scale as mscale
    import matplotlib.pyplot as plt
    import matplotlib.transforms as mtransforms
    import matplotlib.ticker as ticker
    import numpy as np
    
    class SquareRootScale(mscale.ScaleBase):
        """
        ScaleBase class for generating square root scale.
        """
     
        name = 'squareroot'
     
        def __init__(self, axis, **kwargs):
            # note in older versions of matplotlib (<3.1), this worked fine.
            # mscale.ScaleBase.__init__(self)
    
            # In newer versions (>=3.1), you also need to pass in `axis` as an arg
            mscale.ScaleBase.__init__(self, axis)
     
        def set_default_locators_and_formatters(self, axis):
            axis.set_major_locator(ticker.AutoLocator())
            axis.set_major_formatter(ticker.ScalarFormatter())
            axis.set_minor_locator(ticker.NullLocator())
            axis.set_minor_formatter(ticker.NullFormatter())
     
        def limit_range_for_scale(self, vmin, vmax, minpos):
            return  max(0., vmin), vmax
     
        class SquareRootTransform(mtransforms.Transform):
            input_dims = 1
            output_dims = 1
            is_separable = True
     
            def transform_non_affine(self, a): 
                return np.array(a)**0.5
     
            def inverted(self):
                return SquareRootScale.InvertedSquareRootTransform()
     
        class InvertedSquareRootTransform(mtransforms.Transform):
            input_dims = 1
            output_dims = 1
            is_separable = True
     
            def transform(self, a):
                return np.array(a)**2
     
            def inverted(self):
                return SquareRootScale.SquareRootTransform()
     
        def get_transform(self):
            return self.SquareRootTransform()
     
    mscale.register_scale(SquareRootScale)
    
    fig, ax = plt.subplots(1)
    
    ax.plot(np.arange(0, 9)**2, label='$y=x^2$')
    ax.legend()
    
    ax.set_yscale('squareroot')
    ax.set_yticks(np.arange(0,9,2)**2)
    ax.set_yticks(np.arange(0,8.5,0.5)**2, minor=True)
    
    plt.show()
    

    0 讨论(0)
  • 2020-12-21 06:00

    I like lolopop's comment and tom's answer, a more quick and dirty solution would be using set_yticks and set_yticklabels as in the following:

    x = np.arange(2, 15, 2)
    y = x * x
    
    fig = plt.figure()
    ax1 = fig.add_subplot(121)
    ax2 = fig.add_subplot(122)
    
    ax1.plot(x,y)
    
    ax2.plot(x, np.sqrt(y))
    ax2.set_yticks([2,4,6,8,10,12,14])
    ax2.set_yticklabels(['4','16','36','64','100','144','196'])
    
    0 讨论(0)
  • 2020-12-21 06:03

    Matplotlib now offers a powlaw norm. Thus setting power to 0.5 should do the trick!

    C.f. Matplotlib Powerlaw norm

    And their example:

    """
    Demonstration of using norm to map colormaps onto data in non-linear ways.
    """
    
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.colors as colors
    from matplotlib.mlab import bivariate_normal
    
    N = 100
    X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
    
    '''
    PowerNorm: Here a power-law trend in X partially obscures a rectified
    sine wave in Y. We can remove gamma to 0.5 should do the trick using  PowerNorm.
    '''
    X, Y = np.mgrid[0:3:complex(0, N), 0:2:complex(0, N)]
    Z1 = (1 + np.sin(Y * 10.)) * X**(2.)
    
    fig, ax = plt.subplots(2, 1)
    
    pcm = ax[0].pcolormesh(X, Y, Z1, norm=colors.PowerNorm(gamma=1./2.),
                           cmap='PuBu_r')
    fig.colorbar(pcm, ax=ax[0], extend='max')
    
    pcm = ax[1].pcolormesh(X, Y, Z1, cmap='PuBu_r')
    fig.colorbar(pcm, ax=ax[1], extend='max')
    fig.show()
    
    0 讨论(0)
  • 2020-12-21 06:20

    This a simple way to graph sqrt(x)

    import numpy as np
    from matplotlib import pyplot as plt
    
    plt.rcParams["figure.dpi"] = 140
    
    fig, ax = plt.subplots()
    ax.spines["left"].set_position("zero")
    ax.spines["bottom"].set_position("zero")
    ax.spines["right"].set_color("none")
    ax.spines["top"].set_color("none")
    ax.xaxis.set_ticks_position("bottom")
    ax.yaxis.set_ticks_position("left")
    
    origin = [0, 0]
    
    # 45
    plt.plot(
        np.linspace(0, 1, 1000),
        np.sqrt(np.linspace(0, 1, 1000)),
        color="k",
    )
    
    ax.set_aspect("equal")
    plt.xlim(-0.25, 1)
    plt.ylim(0, 1)
    plt.yticks(ticks=np.linspace(0, 1, 6))
    plt.show()
    

    0 讨论(0)
提交回复
热议问题