2011-02-04 8 views
5

Considere el siguiente código:¿Cómo se produce un eje a escala exponencial?

from numpy import log2 
import matplotlib.pyplot as plt 

xdata = [log2(x)*(10/log2(10)) for x in range(1,11)] 
ydata = range(10) 
plt.plot(xdata, ydata) 
plt.show() 

Esto produce el siguiente diagrama: The plot I do not want Mi pregunta es, ¿cómo puedo modificar esta, por lo que la trama, con los mismos datos como entrada, aparece como una línea recta? Esto básicamente requiere escalar el eje x apropiadamente, pero no puedo entender cómo hacerlo. La razón para hacer esto es que estoy mostrando una función que cambia muy poco al principio, pero comienza a fluctuar más hacia el final del intervalo válido, por lo que quiero tener una resolución horizontal más alta hacia el final. Si alguien puede proponer una solución alternativa a mi enfoque, ¡siéntete libre de hacerlo!

Respuesta

5

Aquí es how se hace. Un buen example a seguir. Usted simplemente subclase la clase ScaleBase.

Aquí está su transformación. No es demasiado complicado cuando eliminas todos los formateadores personalizados y esas cosas. Solo un poco detallado.

from numpy import log2 
import matplotlib.pyplot as plt 

from matplotlib import scale as mscale 
from matplotlib import transforms as mtransforms 

class CustomScale(mscale.ScaleBase): 
    name = 'custom' 

    def __init__(self, axis, **kwargs): 
     mscale.ScaleBase.__init__(self) 
     self.thresh = None #thresh 

    def get_transform(self): 
     return self.CustomTransform(self.thresh) 

    def set_default_locators_and_formatters(self, axis): 
     pass 

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

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

     def transform(self, a): 
      return 10**(a/10) 

     def inverted(self): 
      return CustomScale.InvertedCustomTransform(self.thresh) 

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

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

     def transform(self, a): 
      return log2(a)*(10/log2(10)) 

     def inverted(self): 
      return CustomScale.CustomTransform(self.thresh) 


mscale.register_scale(CustomScale) 

xdata = [log2(x)*(10/log2(10)) for x in range(1,11)] 
ydata = range(10) 
plt.plot(xdata, ydata) 

plt.gca().set_xscale('custom') 
plt.show() 
+0

En realidad, usted debería ser capaz de simular cosas sin definir una nueva escala y transformar ... 'ax.xaxis._scale._transform = ax.xaxis._scale. _transform.inverted() 'Esto no funciona por alguna razón, sin embargo ... (o, mejor dicho, funciona hasta que grafiques datos ...) Obviamente, tu ejemplo funciona, ¡aunque bastante prolijo! –

+0

¡Gracias! Descubrí ese ejemplo yo mismo, pero tenía la esperanza de que podría haber una manera más simple. –

2

La forma más sencilla es utilizar semilogy

from numpy import log2 
import matplotlib.pyplot as plt 

xdata = log2(range(1,11)) * (10/log2(10)) 
ydata = range(10) 
plt.semilogy(xdata, ydata) 
plt.show() 

enter image description here

+0

Esto tiene el problema de que no muestra valores y menores que 1. Además, se anula el propósito de tener una resolución horizontal más alta para valores x altos. –

+0

¡Sin duda mostrará valores por debajo de 1! (es decir, 0.001 -> 10^-3). Sin embargo, no mostrará valores iguales o inferiores a 0. Estoy un poco confundido en cuanto a lo que quiere decir con "resolución horizontal más alta para valores x altos" ... ¿Quiere decir la resolución de su trama real (es decir, el número de segmentos en la línea) o dónde están sus xticks ... Alternativamente, podría tener un eje roto ... –

+0

¡Ah! Me acabo de dar cuenta de lo que estás queriendo hacer ... De hecho, quieres el reverso de un semilog-xaxis, ¿verdad? Es decir. ¿Quieres que el eje x crezca exponencialmente, no logarítmicamente? (Por supuesto, eso es esencialmente lo que dijiste en tu pregunta original, me llevó un tiempo atravesar mi grueso cráneo ...) –

Cuestiones relacionadas