En Python la biblioteca más extendida para gráficas 2D y 3D es matplotlib. Permite obtener gráficas de muy buena calidad, con una gran capacidad de control y una curva de aprendizaje moderada. Todos los aspectos de la figura pueden controlarse mediante código. Por más información consultar el sitio de la biblioteca: http://matplotlib.org/.
La siguiente instrucción permite incorporar las gráficas en este documento (sin que se abra una nueva ventana para cada gráfica)
%matplotlib inline
Para poder utilizar Matplotlib desde un programa existe en principio dos opciones. La más directa y tal vez más sencilla es importar el módulo pylab.
from pylab import *
La otra alternativa, más purista, es importar el módulo matplotlib.pyplot (como plt como convención).
import matplotlib.pyplot as plt
La primera forma de usar Matplotlib a través de pylab está diseñada para ser compatible con Matlab, un lenguaje de computación científica muy utilizado.
A continuación un ejemplo de uso sencillo.
from pylab import *
x = linspace(0, 5, 10)
y = x ** 2
figure()
plot(x, y, 'r')
xlabel('x')
ylabel('y')
title('titulo')
show()
Es la forma más directa de iniciarse si uno está familiarizado con Matlab ya que la mayoría de sus funciones están implementadas. Además el código resulta más compacto y sencillo, especialmente para gráficas simples.
subplot(1,2,1)
plot(x, y, 'r--')
subplot(1,2,2)
plot(y, x, 'g*-');
Sin embargo, las opción más recomendada es usar la interfaz provista por pyplot para hacer cosas avanzadas, por ejemplo cuando intervienen varias gráficas y se desea un control más preciso de los elementos. El código puede resultar más complejo y está fuertemente orientado a objetos. A continuación un ejemplo equivalente al anterior.
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # left, bottom, width, height (range 0 to 1)
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('titulo');
Si bien el código es más elaborado, permite mayor control, como se muestra en el siguiente ejemplo.
fig = plt.figure()
axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # main axes
axes2 = fig.add_axes([0.2, 0.5, 0.4, 0.3]) # inset axes
# main figure
axes1.plot(x, y, 'r')
axes1.set_xlabel('x')
axes1.set_ylabel('y')
axes1.set_title('title')
# insert
axes2.plot(y, x, 'g')
axes2.set_xlabel('y')
axes2.set_ylabel('x')
axes2.set_title('insert title');
Existen manejadores de ejes que pueden facilitar la ubicación y distribución de gráficas en una misma figura. Uno de ellos es subplot, el cual se ilustra en los siguientes ejemplos.
fig, axes = plt.subplots()
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title');
fig, axes = plt.subplots(nrows=1, ncols=2)
for ax in axes:
ax.plot(x, y, 'r')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('title')
A modo de ejemplo podemos retomar el ejercicio de la talea y color para visualizar las secuencias de altura y duración resultantes.
import matplotlib.pyplot as plt
def isorritmico(talea, color):
'''crea una melodía isorrítmica a partir de una talea y un color'''
# extiende las secuencias para que tengan la misma cantidad de elementos
clen, tlen = len(color), len(talea)
talea *= clen
color *= tlen
# crea la lista de notas como tuples (altura, duración)
notas = [(x, y) for x, y in zip(color, talea)]
return notas
talea = [1.25, 0.75, 0.5, 0.25, 0.5]
color = [72, 62, 59, 56, 67, 70, 66, 57, 63, 76, 73, 65]
notas = isorritmico(talea, color)
altura_duracion = [list(t) for t in zip(*notas)]
alturas = altura_duracion[0]
duraciones = altura_duracion[1]
fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1)
x = range(len(notas))
ax1.plot(x, alturas, 'r-x')
ax1.set_ylabel('Midi')
ax1.set_title('alturas');
ax2.plot(x, duraciones, 'g--o')
ax2.set_xlabel('nota')
ax2.set_ylabel('negra')
ax2.set_title('duraciones');
Es posible guardar una figura como imagen usando la función savefig de la clase Figura.
fig.savefig("taleacolor.png")
Se pueden controlar varias cosas al guardar una imagen, como por ejemplo los dpi.
fig.savefig("taleacolor.png", dpi=200)
Se pueden agregar leyendas a las gráficas. Esto resulta especialmente útil cuando se superponen gráficas.
x = linspace(0, 5, 10)
fig, ax = plt.subplots()
ax.plot(x, x**2, label="curva 1")
ax.plot(x, x**3, label="curva 2")
ax.legend();
Los colores y estilo de línea se pueden establecer como antes usando el estilo de Matlab.
fig, ax = plt.subplots()
ax.plot(x, x**2, 'b.-') # blue line with dots
ax.plot(x, x**3, 'g--') # green dashed line
ax.set_title('ejemplo lineas');
También se pueden indicar los colores por sus nombres en inglés o su código RGB en valores hexadecimales.
Además es posible indicar un valor de transparencia mediante el parámetro alpha.
fig, ax = plt.subplots()
ax.plot(x, x+1, color="red", alpha=0.5) # half-transparant red
ax.plot(x, x+2, color="#1155dd") # RGB hex code for a bluish color
ax.plot(x, x+3, color="#15cc55") # RGB hex code for a greenish color
ax.set_title('ejemplo lineas y transparencia');
El grosor de la línea se puede controlar mediante el parámetro linewidth y el estilo mediante el parámetro linestle.
Mediante marker y markersize se puede establecer un marcador y su tamaño.
fig, ax = plt.subplots(figsize=(12,6))
ax.plot(x, x+1, color="blue", linewidth=0.25)
ax.plot(x, x+2, color="blue", linewidth=0.50)
ax.plot(x, x+3, color="blue", linewidth=1.00)
ax.plot(x, x+4, color="blue", linewidth=2.00)
# possible linestype options ‘-‘, ‘–’, ‘-.’, ‘:’, ‘steps’
ax.plot(x, x+5, color="red", lw=2, linestyle='-')
ax.plot(x, x+6, color="red", lw=2, ls='-.')
ax.plot(x, x+7, color="red", lw=2, ls=':')
# custom dash
line, = ax.plot(x, x+8, color="black", lw=1.50)
line.set_dashes([5, 10, 15, 10]) # format: line length, space length, ...
# possible marker symbols: marker = '+', 'o', '*', 's', ',', '.', '1', '2', '3', '4', ...
ax.plot(x, x+ 9, color="green", lw=2, ls='*', marker='+')
ax.plot(x, x+10, color="green", lw=2, ls='*', marker='o')
ax.plot(x, x+11, color="green", lw=2, ls='*', marker='s')
ax.plot(x, x+12, color="green", lw=2, ls='*', marker='1')
# marker size and color
ax.plot(x, x+13, color="purple", lw=1, ls='-', marker='o', markersize=2)
ax.plot(x, x+14, color="purple", lw=1, ls='-', marker='o', markersize=4)
ax.plot(x, x+15, color="purple", lw=1, ls='-', marker='o', markersize=8, markerfacecolor="red")
ax.plot(x, x+16, color="purple", lw=1, ls='-', marker='s', markersize=8,
markerfacecolor="yellow", markeredgewidth=2, markeredgecolor="blue");
ax.set_title('ejemplo de estilos de línea');
Es posible definir una grilla y controlar su apariencia, como en el siguiente ejemplo.
fig, axes = plt.subplots(1, 2, figsize=(10,3))
# default grid appearance
axes[0].plot(x, x**2, x, x**3, lw=2)
axes[0].grid(True)
#axes[0].set_xlim((3,5))
axes[0].set_title('Grilla por defecto');
# custom grid appearance
axes[1].plot(x, x**2, x, x**3, lw=2)
axes[1].grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5)
axes[1].set_title('Grilla modificada');
La función hist permite calcular histogramas, como en el siguiente ejemplo.
n = np.random.randn(100000)
fig, axes = plt.subplots()
axes.hist(n)
axes.set_xlim((min(n), max(n)))
axes.set_title("Default histogram");
Existe una serie de funciones especiales para producir otro tipo de gráficos. En el siguiente ejemplo se presentan algunas posibilidades.
xx = np.linspace(-0.75, 1., 100)
n = array([0,1,2,3,4,5])
fig, axes = plt.subplots(1, 4, figsize=(12,3))
axes[0].scatter(xx, xx + 0.25*randn(len(xx)))
axes[0].set_title("scatter")
axes[1].step(n, n**2, lw=2)
axes[1].set_title("step")
axes[2].bar(n, n**2, align="center", width=0.5, alpha=0.5)
axes[2].set_title("bar")
axes[3].fill_between(x, x**2, x**3, color="green", alpha=0.5);
axes[3].set_title("fill_between");