如何在X轴上的相同距离处放置不同的幅度值 [英] How to put different in magnitude values at same distance on x-axis

查看:63
本文介绍了如何在X轴上的相同距离处放置不同的幅度值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Python在同一图上绘制几条直线. 我在x值(在我的代码中用变量q调用)中的值幅值有很大的变化,因此我想将它们在x轴上放置相同的距离,以便在第一部分上有清晰的视野图的.

I'm using Python to plot several straight lines on the same plot. I have a great variability in values magnitude over x values (called with variable q in my code), so I want to put them at the same distance on the x-axis, in order to have a clear vision on the first part of the graph.

这是我的代码:

def c(m,x):
'''
Linear cost function, describing costs for each weight range
:param m: the slope, modelling rates
:param x: the abscissa, modelling quantity ordered
:return: the cost value for each quantity
'''
    return m * x

for i in range(0,9):
    w = np.arange(0., q[9], 0.01)
    plt.plot(w,c(r[i],w),'b--',linewidth=0.3)
    plt.plot( [q[i],breakpoints[i]] , [c(r[i], q[i]), c(r[i], breakpoints[i])], 'r')
    plt.plot(q[i + 1], c(r[i], breakpoints[i]), 'r.')

plt.show()

为简单起见,这是我的代码段中涉及的所有数据:

For the sake of simplicity, here there is all data involved in my code snippet:

如您所见,这是经典的数量折扣研究. 因此,如果仅绘制这些值,由于前q个值保留的空间很小,因此无法区分在第一条直线上发生的情况,请参见以下内容:

As you can see, this is the classical quantity discount study. So, if I simply plot these values, I can't distinguish what is happening at the first straight lines, since little space is reserved to the first q values, see below:

现在,我向您展示前q个值的缩放图:

Now I show you the zoomed graph on first q values:

我考虑过的解决方案是将所有q[]值绘制在相同的距离处:请参见下一张图片. 因此,我想要实现的就是简单地使所有q []值在x轴上的距离相同,而与它们的值无关.我该怎么办?

The solution I have thought about is to plot all q[] values at same distance: see the next picture. So all I want to achieve is simply to have all q[] values at the same distance on x-axis, independently on their value. How can I do this?

推荐答案

如评论中所述,当操纵比例尺以显示不均匀的间距时,直线将不再是直线.

As said in the comments, when manipulating scale to show uneven spacings, straight lines would not be as straight lines any more.

下面是一段代码,该代码实现了问题所希望的比例.

Below is a code that implements a scale like desired in the question.

import numpy as np
from numpy import ma
from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms
from matplotlib.ticker import FixedLocator


class SegmentedScale(mscale.ScaleBase):
    name = 'segmented'

    def __init__(self, axis, **kwargs):
        mscale.ScaleBase.__init__(self)
        self.points = kwargs.get('points',[0,1])
        self.lb = self.points[0]
        self.ub = self.points[-1]

    def get_transform(self):
        return self.SegTrans(self.lb, self.ub, self.points)

    def set_default_locators_and_formatters(self, axis):
        axis.set_major_locator(FixedLocator(self.points))

    def limit_range_for_scale(self, vmin, vmax, minpos):
        return max(vmin, self.lb), min(vmax, self.ub)

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

        def __init__(self, lb, ub, points):
            mtransforms.Transform.__init__(self)
            self.lb = lb
            self.ub = ub
            self.points = points

        def transform_non_affine(self, a):
            masked = a # ma.masked_where((a < self.lb) | (a > self.ub), a)
            return np.interp(masked, self.points, np.arange(len(self.points)))

        def inverted(self):
            return SegmentedScale.InvertedSegTrans(self.lb, self.ub, self.points)

    class InvertedSegTrans(SegTrans):

        def transform_non_affine(self, a):
            return np.interp(a, np.arange(len(self.points)), self.points)
        def inverted(self):
            return SegmentedScale.SegTrans(self.lb, self.ub, self.points)

# Now that the Scale class has been defined, it must be registered so
# that ``matplotlib`` can find it.
mscale.register_scale(SegmentedScale)


if __name__ == '__main__':

    u=  u"""0, 137.13, 0.082
        0.1, 112.46, 0.175
        0.2, 98.23, 0.368
        0.5, 72.38, 0.838
        1, 60.69, 8.932
        10, 54.21, 17.602
        20, 47.71, 48.355
        50, 46.14, 89.358
        100, 41.23, 241.147
        250, 39.77, 0"""

    import io
    import matplotlib.pyplot as plt

    q,r,breakpoints = np.loadtxt(io.StringIO(u), delimiter=", ", unpack=True)

    c = lambda m,x : m*x

    for i in range(0,9):
        w = np.arange(0., q[9], 0.01)
        plt.plot(w,c(r[i],w),'b--',linewidth=0.3)
        plt.plot( [q[i],breakpoints[i]] , [c(r[i], q[i]), c(r[i], breakpoints[i])], 'r')
        plt.plot(q[i + 1], c(r[i], breakpoints[i]), 'r.')

    plt.gca().set_xscale('segmented', points = q)
    plt.show()

除了行中的扭结外,这可能是不希望的,但由于此处使用的刻度类型是必要的结果,因此y轴上的值仍然非常不可读.

Apart from the kinks in the lines, which might not be desired, but are a necessary consequence from the kind of scale used here, the values on the y axis are still quite unreadable.

这篇关于如何在X轴上的相同距离处放置不同的幅度值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆