2011-10-13 33 views
11

definir datosmatplotlib: agregar segundos ejes() con fondo transparente?

x = np.linspace(0,2*np.pi,100) 
y = 2*np.sin(x) 

Plot

fig = plt.figure() 
ax = plt.axes() 
fig.add_subplot(ax) 
ax.plot(x,y) 

Añadir segundo eje

newax = plt.axes(axisbg='none') 

me da ValueError: Unknown element o, a pesar de que hace lo mismo que lo que voy a describir. También puedo ver que esto funciona (sin error) a hacer lo mismo:

newax = plt.axes() 
fig.add_subplot(newax) 
newax.set_axis_bgcolor('none') 

Sin embargo, resulta que el color de fondo de la figura original "gris" (o lo que sea la figura de fondo es)? No entiendo, ya que pensé que esto haría a newax transparente, excepto por los ejes y la caja alrededor de la figura. Incluso si cambio el orden, la misma cosa:

plt.close('all') 
fig = plt.figure() 
newax = plt.axes() 
fig.add_subplot(newax) 
newax.set_axis_bgcolor('none') 
ax = plt.axes() 
fig.add_subplot(ax) 
ax.plot(x,y) 

Esto es sorprendente porque pensé que el fondo de uno podría ser superpuesta a la otra, pero en cualquier caso, es el fondo newax que parece ser visible (o al menos este es el color que veo).

¿Qué está pasando aquí?

Respuesta

37

En realidad, no está agregando un nuevo eje.

Matplotlib detecta que ya hay una trama en esa posición y la devuelve en lugar de un nuevo objeto de ejes.

(Compruébalo por ti mismo. ax y newax será el mismo objeto.)

Probablemente no hay una razón por la que te gustaría, pero aquí es como usted lo haría.

(Además, no llame a newax = plt.axes() y luego llamar fig.add_subplot(newax) Estás haciendo lo mismo dos veces.)

Editar: Con más nuevos (?> = 1.2, creo) versiones de matplotlib, se puede lograr lo mismo que en el siguiente ejemplo utilizando el kwarg label en fig.add_subplot. P.ej. newax = fig.add_subplot(111, label='some unique string')

import matplotlib.pyplot as plt 

fig = plt.figure() 
ax = fig.add_subplot(1,1,1) 

# If you just call `plt.axes()` or equivalently `fig.add_subplot()` matplotlib 
# will just return `ax` again. It _won't_ create a new axis unless we 
# call fig.add_axes() or reset fig._seen 
newax = fig.add_axes(ax.get_position(), frameon=False) 

ax.plot(range(10), 'r-') 
newax.plot(range(50), 'g-') 
newax.axis('equal') 

plt.show() 

enter image description here

Por supuesto, esto se ve horrible, pero es lo que estás pidiendo ...

supongo partir de sus preguntas anteriores que lo que desea añadir una segundo eje x? Si es así, esto es algo completamente diferente.

Si desea vincular los ejes y, haga algo como esto (un tanto detallado ...):

import matplotlib.pyplot as plt 

fig, ax = plt.subplots() 
newax = ax.twiny() 

# Make some room at the bottom 
fig.subplots_adjust(bottom=0.20) 

# I'm guessing you want them both on the bottom... 
newax.set_frame_on(True) 
newax.patch.set_visible(False) 
newax.xaxis.set_ticks_position('bottom') 
newax.xaxis.set_label_position('bottom') 
newax.spines['bottom'].set_position(('outward', 40)) 

ax.plot(range(10), 'r-') 
newax.plot(range(21), 'g-') 

ax.set_xlabel('Red Thing') 
newax.set_xlabel('Green Thing') 

plt.show() 

enter image description here

Si desea tener una, no vinculado eje y oculto, y un totalmente nuevo eje x, entonces usted haría algo como esto:

import matplotlib.pyplot as plt 
import numpy as np 

fig, ax = plt.subplots() 
fig.subplots_adjust(bottom=0.2) 

newax = fig.add_axes(ax.get_position()) 
newax.patch.set_visible(False) 
newax.yaxis.set_visible(False) 

for spinename, spine in newax.spines.iteritems(): 
    if spinename != 'bottom': 
     spine.set_visible(False) 

newax.spines['bottom'].set_position(('outward', 25)) 

ax.plot(range(10), 'r-') 

x = np.linspace(0, 6*np.pi) 
newax.plot(x, 0.001 * np.cos(x), 'g-') 

plt.show() 

enter image description here

Tenga en cuenta que los valores del eje y para todo lo representado en newax nunca se muestran.

Si quisiera, podría incluso llevar esto un paso más allá, y tienen ejes X e Y independientes (no estoy muy seguro de lo que sería el punto de la misma, pero se ve bien ...):

import matplotlib.pyplot as plt 
import numpy as np 

fig, ax = plt.subplots() 
fig.subplots_adjust(bottom=0.2, right=0.85) 

newax = fig.add_axes(ax.get_position()) 
newax.patch.set_visible(False) 

newax.yaxis.set_label_position('right') 
newax.yaxis.set_ticks_position('right') 

newax.spines['bottom'].set_position(('outward', 35)) 

ax.plot(range(10), 'r-') 
ax.set_xlabel('Red X-axis', color='red') 
ax.set_ylabel('Red Y-axis', color='red') 

x = np.linspace(0, 6*np.pi) 
newax.plot(x, 0.001 * np.cos(x), 'g-') 

newax.set_xlabel('Green X-axis', color='green') 
newax.set_ylabel('Green Y-axis', color='green') 


plt.show() 

enter image description here

también puede simplemente añadir una columna adicional en la parte inferior de la trama. A veces, esto es más fácil, especialmente si no quiere tics o elementos numéricos a lo largo de él. No es para tapar una de mis propias respuestas demasiado, pero hay un ejemplo de ello aquí: How do I plot multiple X or Y axes in matplotlib?

Como una cosa pasada, asegúrese de buscar en el parasite axes examples si usted quiere tener los diferentes ejes X e Y unidos a través de una transformación específica.

+0

Sí, de hecho se trataba de los dos ejes ... No obtenía el 'twinx' y ahora' twiny' (supongo que debería haber sabido que el segundo existía) pero no creía necesario que necesitaran ser "vinculado", necesariamente, siempre y cuando el ancho de la trama sea el mismo (porque puedo establecer los límites en ese momento). – hatmatrix

+0

Así que si estaba dispuesto a hacer eso, este primer ejemplo también podría funcionar al desactivar la visibilidad de los otros lomos. Parece que hay tantas variaciones en cada método en matplotlib que estaba buscando algunas funciones "generales" que se pueden aplicar en la mayoría de los casos, sin tener que aprender cada una de las funciones de "conveniencia" disponibles ... pero gracias, esto resuelve todo. Pero el retorno de plt.axes() al mismo objeto fue una sorpresa, pensé que para eso era plt.gca(). Y esto es diferente de Matlab ... – hatmatrix

+0

Bueno, 'plt.axes()' hace un nuevo eje en cualquier otra circunstancia. Simplemente tiene un fragmento de código que comprueba si ya hay un eje en esa posición y lo devuelve (y lo convierte en el eje actual) si es así. (Básicamente, ese es el tercer punto de viñeta en la documentación para 'plt.axes()', aunque hay que leer un poco las líneas ...) –