2011-02-04 9 views
5

Si consideri il seguente codice:Come produrre un asse in scala esponenziale?

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() 

Questo produce il seguente grafico: The plot I do not want La mia domanda è: come posso modificare questo, in modo che la trama, con gli stessi dati come input, appare come una linea retta? Ciò richiede fondamentalmente un ridimensionamento dell'asse x in modo appropriato, ma non riesco a capire come farlo. La ragione per fare questo è che sto visualizzando una funzione che cambia molto poco all'inizio, ma inizia a fluttuare di più verso la fine dell'intervallo valido, quindi voglio avere una risoluzione orizzontale più elevata verso la fine. Se qualcuno può proporre una soluzione alternativa al mio approccio, sentiti libero di farlo!

risposta

5

Ecco how è fatto. Un buon example da seguire. Hai appena sottoclasse la classe ScaleBase.

Ecco la tua trasformazione. Non è troppo complicato quando sbagli tutti i formattatori e le cose personalizzate. Solo un po 'prolisso.

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

In realtà, dovresti essere in grado di riprodurre le patch senza definire una nuova scala e trasformare ... 'ax.xaxis._scale._transform = ax.xaxis._scale. _transform.inverted() 'Questo non funziona per qualche motivo, anche se ... (o, piuttosto, funziona finché non si tracciano dati ...) Ovviamente, il tuo esempio funziona, anche se piuttosto prolisso! –

+0

Grazie! Ho scoperto questo esempio personalmente, ma speravo che potesse esserci un modo più semplice. –

2

Il modo più semplice è quello di utilizzare 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

Questo ha il problema che non mostra valori y inferiori a 1. Inoltre, sconfigge lo scopo di avere una risoluzione orizzontale più alta per valori x alti. –

+0

Mostrerà sicuramente i valori inferiori a 1! (Ad es. 0.001 -> 10^-3) Tuttavia non mostrerà valori pari o inferiori a 0. Sono un po 'confuso su cosa intendi per "risoluzione orizzontale più alta per valori x alti" ... Intendi la risoluzione del tuo grafico reale (ovvero il numero di segmenti nella linea) o il punto in cui i tuoi xticks sono ... In alternativa, potresti avere solo un asse rotto ... –

+0

Ah! Ho appena capito cosa vuoi fare ... Tu vuoi effettivamente il contrario di un semilog-xaxis, giusto? Cioè vuoi che l'asse x cresca in modo esponenziale, non in modo logaritmico? (Naturalmente, questo è essenzialmente ciò che hai detto nella tua domanda iniziale, ci è voluto solo un po 'di tempo per superare il mio grosso cranio ...) –

Problemi correlati