Python对数概率图

时间:2017-01-12 20:48:34

标签: python matplotlib plot axes

我想在对数正态概率图上绘制cdf数据,如下所示:

enter image description here

我希望我的绘图上的轴刻度看起来像那样,只是翻转(在x轴上有概率)。注意,上面的y轴不仅仅是对数刻度。另外我不确定为什么上面的x轴重复1-9而不是10-99等,但忽略那部分。

这是我到目前为止所拥有的。我正在使用该方法按照here

概述制作CDF
mu, sigma = 3., 1. # mean and standard deviation
data = np.random.lognormal(mu, sigma, 1000)

#Make CDF
dataSorted = np.sort(data)
dataCdf = np.linspace(0,1,len(dataSorted))

plt.plot(dataCdf, dataSorted)
plt.gca().set_yscale('log')
plt.xlabel('probability')
plt.ylabel('value')

enter image description here

现在我只需要一种方法来缩放我的x轴,就像上面的图片中的y轴一样。

2 个答案:

答案 0 :(得分:2)

解决此问题的方法是使用称为symlog的对称日志比例。

Symlog是对数图,其在0附近的某个范围内线性地表现(其中正常对数图将显示无限数十年),使得实际上可能存在交叉0的对数图。

可以使用ax.set_xscale('symlog', linthreshx=0.1)在matplotlib中设置Symlog,其中linthreshx表示零附近的线性范围。

在这种情况下,我们希望图形的中心为0.5而不是0,我们实际上可以绘制两个图形并将它们粘在一起。 为了获得所需的结果,现在可以使用要显示的标记以及linthreshx参数进行播放。以下是一个例子。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker
mu, sigma = 3., 1. # mean and standard deviation
data = np.random.lognormal(mu, sigma, 1000)

#Make CDF
dataSorted = np.sort(data)
dataCdf = np.linspace(0,1,len(dataSorted))

fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True)
plt.subplots_adjust(wspace=0.00005)
ax1.plot(dataCdf[:len(dataCdf)/2], dataSorted[:len(dataCdf)/2])
ax2.plot(dataCdf[len(dataCdf)/2:]-1, dataSorted[len(dataCdf)/2:])

ax1.set_yscale('log')
ax2.set_yscale('log')

ax1.set_xscale('symlog', linthreshx=0.001)
ax2.set_xscale('symlog', linthreshx=0.001)

ax1.set_xlim([0.01, 0.5])
ax2.set_xlim([-0.5, -0.01])

ticks = np.array([0.01,0.1,  0.3])
ticks2 = ((1-ticks)[::-1])-1
ax1.set_xticks(ticks)
ax1.xaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax2.set_xticks(ticks2)
ax2.xaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax2.set_xticklabels(ticks2+1)

ax1.spines["right"].set_visible(False)
ax2.spines["left"].set_visible(False)
ax1.yaxis.set_ticks_position('left')
ax2.yaxis.set_ticks_position('right')

ax1.set_xlabel('probability')
ax1.set_ylabel('value')

plt.savefig(__file__+".png")
plt.show()

enter image description here

答案 1 :(得分:0)

我知道有些晚了,但是我遇到了类似的问题并解决了这个问题,所以我想按照matplotlib文档的custom scale example分享解决方案:

import numpy as np
import scipy.stats as stats
from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms
from matplotlib.ticker import Formatter, FixedLocator

class PPFScale(mscale.ScaleBase):
    name = 'ppf'

    def __init__(self, axis, **kwargs):
        mscale.ScaleBase.__init__(self)

    def get_transform(self):
        return self.PPFTransform()

    def set_default_locators_and_formatters(self, axis):
        class VarFormatter(Formatter):
            def __call__(self, x, pos=None):
                return f'{x}'[1:]

        axis.set_major_locator(FixedLocator(np.array([.001,.01,.1,.2,.3,.4,.5,.6,.7,.8,.9,.99,.999])))
        axis.set_major_formatter(VarFormatter())


    def limit_range_for_scale(self, vmin, vmax, minpos):
        return max(vmin, 1e-6), min(vmax, 1-1e-6)

    class PPFTransform(mtransforms.Transform):
        input_dims = output_dims = 1

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

        def transform_non_affine(self, a):
            return stats.norm.ppf(a)

        def inverted(self):
            return PPFScale.IPPFTransform()

    class IPPFTransform(mtransforms.Transform):
        input_dims = output_dims = 1

        def transform_non_affine(self, a):
            return stats.norm.cdf(a)

        def inverted(self):
            return PPFScale.PPFTransform()

mscale.register_scale(PPFScale)


if __name__ == '__main__':
    import matplotlib.pyplot as plt
    mu, sigma = 3., 1. # mean and standard deviation
    data = np.random.lognormal(mu, sigma, 10000)

    #Make CDF
    dataSorted = np.sort(data)
    dataCdf = np.linspace(0,1,len(dataSorted))

    plt.plot(dataCdf, dataSorted)
    plt.gca().set_xscale('ppf')
    plt.gca().set_yscale('log')
    plt.xlabel('probability')
    plt.ylabel('value')
    plt.xlim(0.001,0.999)
    plt.grid()
    plt.show()

output[2]

您可能还想看看我的lognorm demo