将指数衰减函数转换为线性图

时间:2018-10-05 22:41:22

标签: python matplotlib

当使用matplotlib时,我的一些数据基本上是这样的,

handleReportUpdate = (query) => {
//create array of jobs
var getKeywordSummaries = [];

if(query.options.keyword){
    console.log('Keyword');
    let keyword_bracket = []
    query.data.keyword_bracket.forEach(bracket => {
        let getKeywordSummary = tableBuilder.keywords(
            this.state.thisReport.client.data.organic_research,
            bracket
        )
        .then(keyword_summary => {
            keyword_bracket.push(keyword_summary)
        })
        //push each job into the jobs array
        getKeywordSummaries.push(getKeywordSummary);
    });
    //wait until all jobs are done
    Promise.all(getKeywordSummaries).then(function(results) {
        console.log(keyword_bracket)
        let updatedReport =  {
            client: {
                data: {
                    ...this.state.thisReport.client.data,
                    keywordBrackets: keyword_bracket,
                },
                info: {
                   ...this.state.thisReport.client.info,
                   Keyword: query.data.keyword_bracket
             }
            },
            competitors: [...this.state.thisReport.competitors],
            name: this.state.thisReport.name,
            _id: this.state.thisReport._id
        }
        this.setState({
            thisReport: updatedReport
        });
    }
}
}

enter image description here

我想要在matplotlib中实现的是能够更改x轴刻度,使其看起来像在此绘图中一样。

enter image description here

我研究了改变x轴的比例,并尝试对x轴执行对数缩放,但这并没有改变。我想知道是否有一种方法可以使用matplotlib将第一个图形中的东西转换为类似于第二个图形中的xaxis的东西。还是我应该使用其他语言,例如R。

1 个答案:

答案 0 :(得分:0)

我刚刚在github上找到了执行此操作的代码

class LogitScale(mscale.ScaleBase):
    """
    Scales data in range 0,1 to -infty, +infty
    """

    # The scale class must have a member ``name`` that defines the
    # string used to select the scale.
    name = 'logit'

    def __init__(self, axis, **kwargs):
        """
        Any keyword arguments passed to ``set_xscale`` and
        ``set_yscale`` will be passed along to the scale's
        constructor.
        thresh: The degree above which to crop the data.
        """
        mscale.ScaleBase.__init__(self)
        p_min = kwargs.pop("p_min", 1e-5)
        if not (0 <p_min < 0.5):
            raise ValueError("p_min must be between 0 and 0.5 excluded")
        p_max = kwargs.pop("p_max", 1-p_min)
        if not (0.5 < p_max < 1):
            raise ValueError("p_max must be between 0.5 and 1 excluded")
        self.p_min = p_min
        self.p_max = p_max

    def get_transform(self):
        """
        Override this method to return a new instance that does the
        actual transformation of the data.
        """
        return self.LogitTransform(self.p_min, self.p_max)

    def set_default_locators_and_formatters(self, axis):
        expon_major = np.arange(1, 18)
        # ..., 0.01, 0.1, 0.5, 0.9, 0.99, ...
        axis.set_major_locator(FixedLocator(
                list(1/10.**(expon_major)) + \
                [0.5] + \
                list(1-1/10.**(expon_major))
                ))
        minor_ticks = [0.2,0.3,0.4,0.6,0.7, 0.8]
        for i in range(2,17):
            minor_ticks.extend(1/10.**i * np.arange(2,10))
            minor_ticks.extend(1-1/10.**i * np.arange(2,10))
        axis.set_minor_locator(FixedLocator(minor_ticks))
        axis.set_major_formatter(ProbaFormatter())
        axis.set_minor_formatter(ProbaFormatter())

    def limit_range_for_scale(self, vmin, vmax, minpos):
        return max(vmin, self.p_min), min(vmax, self.p_max)

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

        def __init__(self, p_min, p_max):
            mtransforms.Transform.__init__(self)
            self.p_min = p_min
            self.p_max = p_max

        def transform_non_affine(self, a):
            """logit transform (base 10)"""
            p_over = a > self.p_max
            p_under = a < self.p_min
            # saturate extreme values:
            a_sat = np.where(p_over, self.p_max, a)
            a_sat = np.where(p_under, self.p_min, a_sat)
            return np.log10(a_sat / (1-a_sat))

        def inverted(self):
            return LogitScale.InvertedLogitTransform(self.p_min, self.p_max)

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

        def __init__(self, p_min, p_max):
            mtransforms.Transform.__init__(self)
            self.p_min = p_min
            self.p_max = p_max

        def transform_non_affine(self, a):
            """sigmoid transform (base 10)"""
            return 1/(1+10**(-a))

        def inverted(self):
            return LogitScale.LogitTransform(self.p_min, self.p_max)

mscale.register_scale(LogitScale)

if __name__ == '__main__':
    import matplotlib.pyplot as plt
    x = np.array([.5, .8, .9, .999, .9999, .99999])
    y = np.array([1, 1, 1, 1, .1, .01])

    plt.plot(x, y)
    plt.xticks(x)
    plt.gca().set_xscale('logit')
    plt.grid(True)

    plt.show()

我的结果看起来足够好: enter image description here