Pybonacci

Computación Científica con Python en castellano

Manual de introducción a matplotlib.pyplot (II): Creando y manejando ventanas y configurando la sesión

with 6 comments

Esto pretende ser un tutorial del módulo pyplot de la librería matplotlib. El tutorial lo dividiremos de la siguiente forma (que podrá ir cambiando a medida que vayamos avanzando).

  1. Primeros pasos
  2. Creando ventanas, manejando ventanas y configurando la sesión
  3. Configuración del gráfico
  4. Tipos de gráfico I
  5. Tipos de gráfico II
  6. Tipos de gráfico III
  7. Tipos de gráfico IV
  8. Texto y anotaciones (arrow, annotate, table, text…)
  9. Herramientas estadísticas (acorr, cohere, csd, psd, specgram, spy, xcorr, …)
  10. Eventos e interactividad (connect, disconnect, ginput, waitforbuttonpress…)
  11. Miscelánea

[Para este tutorial se ha usado python 2.7.1, ipython 0.11, numpy 1.6.1 y matplotlib 1.1.0]

[DISCLAIMER: Muchos de los gráficos que vamos a representar no tienen ningún sentido físico y los resultados solo pretenden mostrar el uso de la librería].

En todo momento supondremos que se ha iniciado la sesión y se ha hecho


import matplotlib.pyplot as plt

import numpy as np

Como ya comentamos anteriormente, el módulo pyplot de matplotlib se suele usar para hacer pruebas rápidas desde la línea de comandos, programitas cortos o programas donde los gráficos serán, en general, sencillos.

Normalmente, cuando iniciamos la sesión, esta no está puesta en modo interactivo. En modo interactivo, cada vez que metemos código nuevo relacionado con el gráfico o la ventana (recordad, una instancia de matplotlib.axes.Axes o de matplotlib.figure.Figure, respectivamente), este se actualizará. Cuando no estamos en modo interactivo, el gráfico no se actualiza hasta que llamemos a show() (si no hay una ventana abierta) o draw() (normalmente no lo usaréis para nada) explícitamente. Veamos como es esto:

Si acabamos de iniciar sesión deberíamos estar en modo no interactivo. Para comprobarlo hacemos lo siguiente:

plt.isinteractive()
False

Si el resultado es False significa que estamos en modo no interactivo. Esto significa que si hacemos lo siguiente:

plt.plot([1,2,3,4,5])

No lanzará una ventana hasta que lo pidamos explícitamente mediante:

plt.show()

Podemos conmutar a modo interactivo o no usando plt.ion() y plt.ioff(), que lo que hacen es poner el modo interactivo en ‘on’ o en ‘off’, respectivamente. Como está en off (recordad que plt.isinteractive() nos ha dado False, lo que significa que está en ‘off’), si ahora  hacemos lo siguiente (cerrad antes cualquier ventana de gráficos que tengáis abierta):

plt.ion()
plt.plot([1,2,3,4])

Vemos que directamente se abre una ventana nueva sin necesidad de llamar a plt.show(). Yo suelo usar ipython así para ir probando cosas y cuando ya acierto con como quiero que me salgan los gráficos voy a spyder, donde tengo el programa que esté haciendo, y ya escribo el código que necesito con la interfaz orientada a objetos.

Jugad un poco con plt.isinteractive(), plt.ion(), plt.ioff(), plt.show() y plt.draw() para estar más familiarizados con el funcionamiento.

Lo siguiente que veremos es plt.hold() y plt.ishold(). plt.hold es un conmutador para decir si queremos que los gráficos se sobreescriban, que en el mismo gráfico tengamos diferentes gráficas representadas, o para que el gráfico se limpie y se dibuje la nueva gráfica cada vez. Si usamos plt.ishold() nos ‘responderá’ True o False. Si acabáis de iniciar sesión, normalmente estará en True.

plt.ishold()
True

Como está en True, si hacemos lo siguiente:

plt.plot(np.random.rand(10))
plt.plot(np.random.rand(10))
plt.show()

Obtendremos lo siguiente:

Si el modo ‘hold’ estuviera en False, solo se habría conservado el último plot y solo veríamos una línea de las dos (probadlo usando plt.hold() y plt.ishold()).

Si estamos en modo interactivo (plt.ion()) y queremos borrar todos los gráficos (matplotlib.axes.Axes), títulos, …, de la ventana (matplotlib.figure.Figure) podemos usar plt.clf() y nos volverá a dejar el ‘lienzo’ limpio.

Si seguimos en modo interactivo (plt.ion()) y queremos cerrar la ventana podemos usar plt.close().

Imaginaos que ahora queréis trabajar con varias ventanas de gráficos simultáneamente donde en una dibujáis unos datos y en la otra otro tipo de datos y los queréis ver simultáneamente. Podemos hacer esto dándole nombre (o número) a las ventanas con las que vamos a trabajar. Veamos un ejemplo:

plt.figure('scatter') # Crea una ventana titulada 'scatter'
plt.figure('plot')    # Crea una ventana titulada 'plot'
a = np.random.rand(100) # Generamos un vector de valores aleatorios
b = np.random.rand(100) # Generamos otro vector de valores aleatorios
plt.figure('scatter') # Le decimos que la ventana activa en la que vamos a dibujar es la ventana 'scatter'
plt.scatter(a,b)  # Dibujamos un scatterplot en la ventana 'scatter'
plt.figure('plot') # Ahora cambiamos a la ventana 'plot'
plt.plot(a,b)

Y os quedaría algo como lo siguiente:

Es decir, podemos ir dibujando en varias ventanas a la vez. Podéis probar a cerrar una de las dos ventanas, limpiar la otra, crear una nueva,… Haciendo una llamada a plt.figure() también podemos definir la resolución del gráfico, el tamaño de la figura,…

Pero yo no quiero dibujar los gráficos en dos ventanas, yo quiero tener varios gráficos en la misma. Perfecto, también podemos hacer eso sin problemas con la ayuda de plt.subplot(). Con plt.subplot() podemos indicar el número de filas y columnas que corresponderán a como dividimos la ventana. En el siguiente ejemplo se puede ver dos áreas de gráfico en la misma ventana:

plt.ion()  # Nos ponemos en modo interactivo
plt.subplot(1,2,1)  # Dividimos la ventana en una fila y dos columnas y dibujamos el primer gráfico
plt.plot((1,2,3,4,5))
plt.subplot(1,2,2)  # Dividimos la ventana en una fila y dos columnas y dibujamos el segundo gráfico
plt.plot((5,4,3,2,1))

Obteniendo el siguiente gráfico:

Os dejo como ejercicio ver como podéis conseguir la siguiente gráfica (si no sabéis como dejad un comentario) y con ello creo que habréis entendido perfectamente el uso de plt.subplot():

Por último, vamos a ver como configurar la sesión para ahorrarnos escribir código de más. Por ejemplo, imaginaos que queréis que todas las líneas sean más gruesas por defecto porque os gustan más así, que queréis usar otro tipo de fuente sin escribirlo explícitamente cada vez que hacéis un gráfico, que los gráficos se guarden siempre con una resolución superior a la que viene por defecto,… Para ello podéis usar plt.rc(), plt.rcParams, plt.rcdefaults(). En este caso vamos a usar plt.rc(), podréis encontrar más información sobre como configurar matplotlib en este enlace. Veamos un ejemplo para ver como funciona todo esto:

plt.ion()  # Nos ponemos en modo interactivo
plt.figure('valores por defecto')  # Creamos una ventana donde dibujamos el gráfico con la configuración por defecto
plt.suptitle('Titulo valores por defecto')  # Esto sirve para poner título dentro de la ventana
plt.plot((1,2,3,4,5), label = 'por defecto')  # Hacemos el plot
plt.legend(loc = 2)  # Colocamos la leyenda en la esquina superior izquierda

plt.rc('lines', linewidth = 2)  # A partir de aquí todas las líneas que dibujemos irán con ancho doble
plt.rc('font', size = 18)  # A partir de aquí las fuentes que aparezcan en cualquier gráfico en la misma sesión tendrán mayor tamaño
plt.figure('valores modificados')  # Creamos una ventana donde dibujamos el gráfico con la configuración por defecto
plt.suptitle('Titulo valores modificados')  # Esto sirve para poner título dentro de la ventana
plt.plot((1,2,3,4,5), label = u'linea más ancha y letra más grande')  # Hacemos el plot
plt.legend(loc = 2)  # Colocamos la leyenda en la esquina superior izquierda

Después de usar plt.rc() para modificar un parámetro esa modificación será para toda la sesión a no ser que lo volvamos a modificar explícitamente o a no ser que usemos plt.rcdefaults(), que devolverá todos los parámetros a los valores por defecto.

Si no has visto el primer capítulo de esta serie échale un ojo ahora o, si prefieres, puedes pasar a la siguiente parte.

About these ads

Written by Kiko

19 de mayo de 2012 at 20:31

6 comentarios

Subscribe to comments with RSS.

  1. Kiko, he intentado hacer la distribución de la penúltima figura, con un gráfico en la parte superior y dos en la inferior, pero no me sale :$ ¿Puedes dar la solución?

    Edit: Ya lo sé :D http://matplotlib.org/users/tight_layout_guide.html

    Juanlu001

    22 de noviembre de 2012 at 12:19

  2. plt.subplot(211)
    plt.subplot(223)
    plt.subplot(224)

    kiko

    22 de noviembre de 2012 at 12:30

    • Te sorprendería la de veces que releo artículos *del blog* para acordarme de cosas o aprender a hacerlas, incluso aunque los haya escrito yo. ¡Me encanta! :P

      Juanlu001

      22 de noviembre de 2012 at 16:17

  3. Hola he intentado hacer el ejercicio de dos arriba y uno abajo. He intentado usar la secuencia :

    (2,2,1) # dos filas dos columnas escribo en el gráfico 1 (imagino que será el gráfico 1,1)
    (2,2,2) #dos filas dos columnas escribo en el gráfico 2 (que imagino que será el gráfico 1,2)
    (2,1,3) # dos filas dos columnas escribo en el gráfico 3 ( pensaba que el 3 se correspondería al de la fila de abajo)

    Esta secuencia me da error, y no entiendo muy bien por que. Gracias

    Oscar

    30 de noviembre de 2013 at 13:50

    • La última te da error porque con (2, 1, 3) estás diciendo «dos filas, una columna, tercer gráfico» (aunque antes hayas dicho que hay dos columnas), pero si hay dos filas y una columna solo tienes los subplots 1 y 2 (de ahí el IndexError). Por tanto (2, 1, 2) te daría el subplot de abajo centrado. Espero que te aclare :)

      Juanlu001

      3 de diciembre de 2013 at 20:50

      • Tal como comenta JuanLu. El índice se referencia al layout que defines.

        P.D.: Siento no haber contestado antes.

        Kiko

        3 de diciembre de 2013 at 23:11


¡Deja un comentario!

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 1.283 seguidores

%d personas les gusta esto: