2016-01-25 7 views
7

Sto realizzando il grafico seguente in matplotlib, utilizzando tra l'altro plt.ticklabel_format(axis='y',style='sci',scilimits=(0,3)). Questo produce un asse y come così:Stampa con asse scientifico, modifica del numero di cifre significative

enter image description here

Ora il problema è che io voglio l'asse y per avere le zecche da [0, -2, -4, -6, -8, -12]. Ho giocato con lo scilimits ma senza successo.

Come si può forzare le zecche ad avere solo una cifra significativa e zero zeri finali, e galleggiare quando richiesto?

MWE aggiunto di seguito:

import matplotlib.pyplot as plt 
import numpy as np 

t = np.arange(0.0, 10000.0, 10.) 
s = np.sin(np.pi*t)*np.exp(-t*0.0001) 

fig, ax = plt.subplots() 

ax.tick_params(axis='both', which='major') 
plt.ticklabel_format(style='sci', axis='x', scilimits=(0,3)) 
plt.plot(t,s) 

plt.show() 
+0

È possibile aggiungere codice tagliato e passabile? – atomh33ls

+1

http://stackoverflow.com/help/mcve – atomh33ls

+0

scuse fatte ora – Astrid

risposta

1

Quando mi sono imbattuto in questo problema, il meglio che potevo venire con era di usare un costume FuncFormatter per le zecche. Tuttavia, non ho trovato alcun modo per farlo visualizzare la scala (ad esempio 1e5) insieme all'asse. La soluzione facile era includerla manualmente con l'etichetta tick.

Scusate se questo non risponde pienamente alla domanda, ma può bastare come un relativamente semplice soluzione al problema :)

Nel MWE mia soluzione sembra un po 'come questo:

import matplotlib.pyplot as plt 
from matplotlib.ticker import FuncFormatter 
import numpy as np 


def tickformat(x): 
    if int(x) == float(x): 
     return str(int(x)) 
    else: 
     return str(x)   


t = np.arange(0.0, 10000.0, 10.) 
s = np.sin(np.pi*t)*np.exp(-t*0.0001) 

fig, ax = plt.subplots() 

ax.tick_params(axis='both', which='major') 
plt.plot(t,s) 

fmt = FuncFormatter(lambda x, pos: tickformat(x/1e3)) 
ax.xaxis.set_major_formatter(fmt) 

plt.xlabel('time ($s 10^3$)') 

plt.show() 

Nota che l'esempio manipola l'asse x!

enter image description here

Naturalmente, questo potrebbe essere realizzato ancora più semplice da ri-scalare i dati. Tuttavia, presumo che tu non voglia toccare i dati e solo manipolare l'asse.

+0

Grazie per questo, piccola soluzione. È molto strano che non ci sia apparentemente un buon modo per farlo. – Astrid

+1

Sono d'accordo, ma forse uno dei veri guru di matplotlib verrà dopo e fornirà una soluzione semplice e pratica;) – kazemakase

+0

Esattamente, si può solo sperare :) – Astrid

0

Non vedo un modo ovvio per farlo tramite le manopole esistenti su ScalarFormatter. Qualcosa di simile a questo:

import matplotlib.pyplot as plt 
import numpy as np 
import matplotlib.ticker as mticker 

t = np.arange(0.0, 10000.0, 10.) 
s = np.sin(np.pi*t)*np.exp(-t*0.0001) 

class EpiCycleScalarFormatter(mticker.ScalarFormatter): 
    def _set_orderOfMagnitude(self, rng): 
     # can just be super() in py3, args only needed in LPy 
     super(EpiCycleScalarFormatter, self)._set_orderOfMagnitude(rng) 
     if self.orderOfMagnitude != 0: 
      self.orderOfMagnitude -= 1 


fig, ax = plt.subplots() 

ax.tick_params(axis='both', which='major') 
ax.yaxis.set_major_formatter(EpiCycleScalarFormatter()) 
ax.xaxis.set_major_formatter(EpiCycleScalarFormatter()) 
plt.ticklabel_format(style='sci', axis='x', scilimits=(0,3)) 
plt. 
plt.show()plot(t,s) 

enter image description here

risolverà il vostro problema. Prendi nota del nome della sottoclasse, dato che questo è solo l'aggiunta di epicicli (sembrano funzionare, ma aggiungono solo più complessità) al codice esistente. Questo tocca anche parti private della biblioteca che potremmo interrompere in qualsiasi momento.