python - How to put different in magnitude values at same distance on x-axis -
i'm using python plot several straight lines on same plot. have great variability in values magnitude on x values (called variable q
in code), want put them @ same distance on x-axis, in order have clear vision on first part of graph.
here code:
def c(m,x): ''' linear cost function, describing costs each weight range :param m: slope, modelling rates :param x: abscissa, modelling quantity ordered :return: cost value each quantity ''' return m * x 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 sake of simplicity, here there data involved in code snippet:
as can see, classical quantity discount study. so, if plot these values, can't distinguish happening @ first straight lines, since little space reserved first q values, see below:
now show zoomed graph on first q values:
the solution have thought plot q[]
values @ same distance: see next picture. want achieve have q[] values @ same distance on x-axis, independently on value. how can this?
as said in comments, when manipulating scale show uneven spacings, straight lines not straight lines more.
below code implements scale desired in question.
import numpy np numpy import ma matplotlib import scale mscale matplotlib import transforms mtransforms 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 = # 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) # scale class has been defined, must registered # ``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 plt q,r,breakpoints = np.loadtxt(io.stringio(u), delimiter=", ", unpack=true) c = lambda m,x : m*x 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()
apart kinks in lines, might not desired, necessary consequence kind of scale used here, values on y axis still quite unreadable.
Comments
Post a Comment