2012-05-09 30 views
49

Tengo una pregunta muy simple. Necesito tener un segundo eje x en mi diagrama y quiero que este eje tenga un cierto número de tics que corresponden a cierta posición del primer eje.Cómo agregar un segundo eje x en matplotlib

Probemos con un ejemplo. Aquí estoy trazando la masa oscura la materia como una función del factor de expansión, definido como 1/(1 + z), que varía de 0 a 1.

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

me gustaría tener otro eje x, en la parte superior de mi gráfica, mostrando la z correspondiente para algunos valores del factor de expansión. ¿Es eso posible? En caso afirmativo, ¿cómo puedo tener xtics ax

+0

¿Qué biblioteca de trazado está utilizando? – sth

+0

Las funciones que está utilizando no están incorporadas en python; supongo que está hablando de [matplotlib] (http://matplotlib.sourceforge.net/)? Si es así, la pregunta [¿Cómo trazar múltiples ejes x o y en matplotlib?] (Http: // stackoverflow.com/questions/3918028/how-do-i-plot-multiple-x-or-y-axes-in-matplotlib) parece cubrir esto. – James

+0

Edité el título, sí, estoy usando matplotlib. – Brian

Respuesta

68

estoy tomando el ejemplo de los comentarios en @ respuesta de Dhara, parece que desea establecer una lista de new_tick_locations por una función del antiguo eje x al nuevo eje x. El tick_function continuación se lleva en una matriz numpy de puntos, los asigna a un nuevo valor y los formatos:

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

exactamente lo que necesitaba – eusoubrasileiro

+1

Si desea agregar un título también, vea esta pregunta: http://stackoverflow.com/questions/12750355/python-matplotlib-figure-title-overlaps-axes-label-when-using- Twink – szmoore

+0

@Hooked, ¿alguna idea si es posible esto con una de las escalas en la escala de registro? – tiago

12

Puede usar twiny para crear 2 escalas de eje x. Por ejemplo:

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

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

Salida: enter image description here

+0

Lo siento pero eso no es lo que he preguntado. No es necesario trazar las funciones en la misma parcela con diferentes ejes. Solo necesito tener un segundo eje x, en la parte superior de mi diagrama, marcado en correspondencia con alguna posición especial en el primer eje x. – Brian

+0

A continuación, simplemente agregue un segundo eje ficticio con el rango que desee y desactívelo. Vea mi respuesta editada – Dhara

+0

Lo siento pero su código no funciona. Lo copié y pegué y luego el segundo eje X se superpone con el primero. – Brian

7

Responder a su pregunta en los comentarios de la respuesta de Dhara: "me gustaría en el segundo x -axis estos tics: (7,8,99) correspondientes a la posición del eje x 10, 30, 40. ¿Es posible de alguna manera? " Sí, lo es.

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

Usted obtendrá: enter image description here

5

Si usted quiere que su eje superior como una función de los ejes inferiores tic-valores:

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

Da:

enter image description here

+0

+1 establecer el límite fue lo que estaba buscando – dashesy

0

Estoy obligado a publicar esto como una n respuesta en lugar de un comentario debido a la baja reputación. Tuve un problema similar al de Matteo. La diferencia es que no tenía un mapa desde mi primer eje x hasta mi segundo eje x, solo los valores x mismos. Así que quise establecer los datos en mi segundo eje x directamente, no en los tics, sin embargo, no hay axes.set_xdata. Yo era capaz de usar la respuesta de Dhara hacer esto con una modificación:

ax2.lines = [] 

en lugar de utilizar:

ax2.cla() 

Cuando está en uso también se aclaró mi parcela de ax1.

+1

Esta sería una mejor respuesta si proporcionó el ejemplo del código, en lugar de solo los cambios de la respuesta de Dhara. – Benjamin

Cuestiones relacionadas