2012-05-09 11 views
49

Ho una domanda molto semplice. Ho bisogno di avere un secondo asse x sul mio grafico e voglio che questo asse abbia un certo numero di tic che corrisponde a certe posizioni del primo asse.Come aggiungere un secondo asse x in matplotlib

Proviamo con un esempio. Qui sto tramando la massa scura questione in funzione del fattore di espansione, definito come 1/(1 + z), che varia da 0 a 1.

semilogy(1/(1+z),mass_acc_massive,'-',label='DM') 
xlim(0,1) 
ylim(1e8,5e12) 

desidero avere un altro asse x, in cima alla mia trama, mostrando la z corrispondente per alcuni valori del fattore di espansione. È possibile? Se sì, come posso avere xtics ax

+0

Quale libreria di stampa stai usando? – sth

+0

Le funzioni che stai utilizzando non sono integrate in python - presumo tu stia parlando di [matplotlib] (http://matplotlib.sourceforge.net/)? In tal caso, la domanda [Come si stampano più assi xey in matplotlib?] (Http: // stackoverflow.it/questions/3918028/how-do-i-plot-multiple-x-or-y-axes-in-matplotlib) sembra coprirlo. – James

+0

Ho modificato il titolo, sì sto usando matplotlib. – Brian

risposta

68

sto prendendo spunto dai commenti di @ risposta di Dhara, suona come si desidera impostare un elenco di new_tick_locations da una funzione dal vecchio asse x al nuovo asse x. Il tick_function seguito prende in un array NumPy di ​​punti, loro mappe per un nuovo valore e formati:

import numpy as np 
import matplotlib.pyplot as plt 

fig = plt.figure() 
ax1 = fig.add_subplot(111) 
ax2 = ax1.twiny() 

X = np.linspace(0,1,1000) 
Y = np.cos(X*20) 

ax1.plot(X,Y) 
ax1.set_xlabel(r"Original x-axis: $X$") 

new_tick_locations = np.array([.2, .5, .9]) 

def tick_function(X): 
    V = 1/(1+X) 
    return ["%.3f" % z for z in V] 

ax2.set_xlim(ax1.get_xlim()) 
ax2.set_xticks(new_tick_locations) 
ax2.set_xticklabels(tick_function(new_tick_locations)) 
ax2.set_xlabel(r"Modified x-axis: $1/(1+X)$") 
plt.show() 

enter image description here

+0

esattamente ciò di cui avevo bisogno – eusoubrasileiro

+1

Se si desidera aggiungere anche un titolo, vedere questa domanda: http://stackoverflow.com/questions/12750355/python-matplotlib-figure-title-overlaps-axes-label-when-using- twiny – szmoore

+0

@Hooked, qualche idea se è possibile farlo con una delle scale nella scala di registro? – tiago

12

È possibile utilizzare twiny per creare 2 scale dell'asse x. Per esempio:

import numpy as np 
import matplotlib.pyplot as plt 

fig = plt.figure() 
ax1 = fig.add_subplot(111) 
ax2 = ax1.twiny() 

a = np.cos(2*np.pi*np.linspace(0, 1, 60.)) 

ax1.plot(range(60), a) 
ax2.plot(range(100), np.ones(100)) # Create a dummy plot 
ax2.cla() 
plt.show() 

Rif: http://matplotlib.sourceforge.net/faq/howto_faq.html#multiple-y-axis-scales

uscita: enter image description here

+0

Mi dispiace ma non è quello che ho chiesto. Non ho bisogno di tracciare le funzioni sulla stessa trama con assi diversi. Ho solo bisogno di avere un secondo asse x, in cima alla mia trama, spuntato in corrispondenza di qualche posizione speciale sul primo asse x. – Brian

+0

Quindi basta aggiungere un 2 ° asse fittizio con l'intervallo desiderato e cancellarlo. Vedi la mia risposta modificata – Dhara

+0

Siamo spiacenti, ma il tuo codice non funziona. L'ho copiato e incollato e quindi il secondo asse x si sovrappone al primo. – Brian

7

rispondere alla tua domanda nei commenti la risposta di Dhara: "Vorrei al secondo x -è un asse di questi tic: (7,8,99) corrispondente alla posizione dell'asse x 10, 30, 40. È possibile in qualche modo? " Sì, lo è.

import numpy as np 
import matplotlib.pyplot as plt 

fig = plt.figure() 
ax1 = fig.add_subplot(111) 

a = np.cos(2*np.pi*np.linspace(0, 1, 60.)) 
ax1.plot(range(60), a) 

ax1.set_xlim(0, 60) 
ax1.set_xlabel("x") 
ax1.set_ylabel("y") 

ax2 = ax1.twiny() 
ax2.set_xlabel("x-transformed") 
ax2.set_xlim(0, 60) 
ax2.set_xticks([10, 30, 40]) 
ax2.set_xticklabels(['7','8','99']) 

plt.show() 

Otterrete: enter image description here

5

Se volete che il vostro asse superiore ad una funzione dell'asse inferiori tick-valori:

import matplotlib.pyplot as plt 

fig, ax1 = plt.subplots() 

ax1 = fig.add_subplot(111) 

ax1.plot(range(5), range(5)) 

ax1.grid(True) 

ax2 = ax1.twiny() 
ax1Xs = ax1.get_xticks() 

ax2Xs = [] 
for X in ax1Xs: 
    ax2Xs.append(X * 2) 

ax2.set_xticks(ax1Xs) 
ax2.set_xbound(ax1.get_xbound()) 
ax2.set_xticklabels(ax2Xs) 

title = ax1.set_title("Upper x-axis ticks are lower x-axis ticks doubled!") 
title.set_y(1.1) 
fig.subplots_adjust(top=0.85) 

fig.savefig("1.png") 

Dà:

enter image description here

+0

+1 l'impostazione del limite era quello che stavo cercando – dashesy

0

Sono costretto a postare questo come n risposta invece di un commento a causa della bassa reputazione. Ho avuto un problema simile a Matteo. La differenza è che non avevo nessuna mappa dal mio primo asse x al mio secondo asse x, solo i valori x stessi. Quindi volevo impostare i dati sul mio secondo asse x direttamente, non sui tick, tuttavia non c'è lo axes.set_xdata. Sono stato in grado di usare la risposta di Dhara a che fare questo con una modifica:

ax2.lines = [] 

invece di utilizzare:

ax2.cla() 

Quando è in uso anche cancellato il mio appezzamento da ax1.

+1

Questa sarebbe una risposta migliore se hai fornito l'esempio di codice, anziché solo i cambiamenti dalla risposta di Dhara. – Benjamin

Problemi correlati