2011-05-26 27 views
15

No sé cómo se llama esto, ni siquiera cómo se describe, por lo que el título puede ser un poco engañoso.

El primer gráfico adjunto se creó con pyplot. Me gustaría dibujar una línea recta que recorre todos los gráficos en lugar de los tres puntos rojos que uso actualmente. ¿Es posible en pyplot? La segunda imagen es lo que estoy buscando. Currently What I am looking forTrazando una línea en varios gráficos

+0

¿Cómo se determina dónde tomar los puntos rojos? – Sword22

+0

@ Sword22 Todos los gráficos tienen el mismo eje x. Los puntos rojos son básicamente una lista de valores del eje x. – Artium

Respuesta

24

Puede sacar esto adelante girando fuera de recorte en las líneas correspondientes. Probablemente hay una forma más limpia de hacer esto - es posible que pueda dibujar líneas en el bastidor principal directamente - pero los siguientes trabajado para mí:

from matplotlib import pyplot as plt 
from numpy import arange, sin, cos 

xx = arange(100) 
cut = (xx > 0) & (xx % 17 == 0) 
y1 = sin(xx) 
y2 = (xx**2) % 2.0+cos(xx+0.5) 

fig = plt.figure() 
ax1 = fig.add_subplot(211) 
ax1.plot(xx, y1, c="blue",zorder=1) 
ax1.scatter(xx[cut], y1[cut], c="red",zorder=2) 
ax2 = fig.add_subplot(212) 
ax2.plot(xx, y2, c="green",zorder=1) 
ax2.scatter(xx[cut], y2[cut], c="red",zorder=2) 

for x in xx[cut]: 
    ax1.axvline(x=x,ymin=-1.2,ymax=1,c="red",linewidth=2,zorder=0, clip_on=False) 
    ax2.axvline(x=x,ymin=0,ymax=1.2,c="red",linewidth=2, zorder=0,clip_on=False) 

plt.draw() 
fig.savefig('pic.png') 

Con un poco más de trabajo que podría modificar el trazado de líneas de manejar el caso general de múltiples ventanas de subtrama, pero soy profundamente vago. : ^)

example of cross-subplot vertical lines

1

me gustaría probar axvline(x, y1, y2) (link), pero no creo que ninguna de las opciones en pyplot dibujará algo que se extiende por la mayoría de las subparcelas/gráficos.

Si ese es el caso, simplemente trataría de dibujar la misma línea vertical en cada punto del gráfico, esperando que el mismo intento se transmita al espectador.

+0

Disculpas. Mi respuesta no presenta ninguna información nueva que la tuya no tenga. Ya había armado un ejemplo, así que pensé que publicaría de todos modos. +1 a ti por ser mucho más rápido. – bernie

+1

@Adam Bernier Nunca se disculpe por proporcionar un código fuente de ejemplo ... –

+0

de acuerdo con Jonathan, una respuesta con código fuente y ejemplos es mucho mejor que uno sin, ¡la velocidad no cuenta! –

10

documentación pertinente:
http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.axvline

Editar: @DSM's answer ya era mucho mejor que la mía he incorporado vergonzosamente poco de esa respuesta en un intento de hacer mi respuesta menos pobres.

He intentado manejar el caso algo general de múltiples subtramas en una columna (es decir, no el caso aún más general de múltiples subparcelas, por ejemplo, en una cuadrícula).

Gracias, @DSM, por su respuesta y @Artium por la pregunta.

import matplotlib.pyplot as plt 
import numpy as np 

def main(): 
    fig = plt.figure() 

    x = np.arange(20) 
    y1 = np.cos(x) 
    y2 = (x**2) 
    y3 = (x**3) 
    yn = (y1,y2,y3) 
    cut = (x > 0) & (x % 2 == 0) 
    COLORS = ('b','g','k') 

    for i,y in enumerate(yn): 
     ax = fig.add_subplot(len(yn),1,i+1) 

     ax.plot(x, y,ls='solid', color=COLORS[i], zorder=1) 
     ax.scatter(x[cut], y[cut], c='r', zorder=2) 

     if i != len(yn) - 1: 
      ax.set_xticklabels(()) 

     for j in x[cut]: 
      if i != len(yn) - 1: 
       ax.axvline(x=j, ymin=-1.2, ymax=1, 
          c='r', lw=2, zorder=0, clip_on=False) 
      else: 
       ax.axvline(x=j, ymin=0, ymax=1, 
          c='r', lw=2, zorder=0, clip_on=False) 

    fig.suptitle('Matplotlib Vertical Line Example') 
    plt.show() 

if __name__ == '__main__': 
    main() 

enter image description here

+0

Me gusta mucho su respuesta. Sin embargo, en mi caso, los márgenes horizontales y verticales están presentes si ejecuto tu código. ¿Alguna idea de cómo eliminarlos? – Rickson

+0

Para ser más precisos. En mi caso, el rango del eje x es [-5,20] en lugar de [0,20] y f. mi.para el último diagrama, el rango de yaxis es [-1000,8000] en lugar de [0,7000]. Intenté casi cualquier cosa (autoescala, eje ajustado, relim, etc.) sin éxito. – Rickson

+0

Si alguien más está interesado: Es causado por la generación de los puntos de dispersión. – Rickson

5

[Actualización 03/2013] En revisiones más recientes de matplotlib, hay ConnectionPatch que simplifica enormemente esta tarea. Es particularmente útil cuando hay más de dos subtramas que necesitan ser cubiertas.

from matplotlib import pyplot as plt 
from matplotlib.patches import ConnectionPatch 
from numpy import arange, sin, cos 

xx = arange(100) 
cut = (xx > 0) & (xx % 17 == 0) 
y1 = sin(xx) 
y2 = (xx**2) % 2.0+cos(xx+0.5) 

fig = plt.figure() 
ax1 = fig.add_subplot(211) 
ax1.plot(xx, y1, c="blue") 
ax1.scatter(xx[cut], y1[cut], c="red") 
ax2 = fig.add_subplot(212) 
ax2.plot(xx, y2, c="green") 
ax2.scatter(xx[cut], y2[cut], c="red") 

for x in xx[cut]: 
    con = ConnectionPatch(xyA=(x, -1.5), xyB=(x, 1.5), 
     coordsA="data", coordsB="data", axesA=ax2, axesB=ax1, 
     arrowstyle="-", linewidth=2, color="red") 
    ax2.add_artist(con) 

plt.draw() 
fig.savefig('pic.png') 
Cuestiones relacionadas