.. ayuda sobre plots en python
********************
Gráficos con python
********************
El lenguaje python permite realizar una amplia variedad de
visualizaciones de datos. La misma se realiza mediante la ayuda
de módulos (como math o numpy) que están destinados a brindar
herramientas de visualización.
En la lista que sigue se presentan algunos de los módulos más usados.
El objetivo no es aprenderlos, sino saber que existen varias opciones
y disminuir un poco la confusión que se puede producir al principio
al buscar ayuda y bibliografía:
* `Matplotlib `_
* `Seaborn `_
* `Plotly `_
* `Bokeh `_
* `Altair `_
* `Pygal `_
* `Pandas `_
* `Plotnine `_
La elección de una de estas herramientas para hacer un gráfico depende del
contexto, para qué se quiere hacer el gráfico, dónde se va a mostrar y a partir
de qué datos. Así, por ejemplo, Plotly, Bokeh y Altair devuelven gráficos en
HTML para ser mostrados en páginas web, Pygal genera gráficos vectoriales y
Pandas grafica datos guardados en cierto tipo especial de estructura.
En este tutorial (y en la materia) usaremos solamente Matplotlib.
El módulo Matplotlib
========================
Matplotlib es un módulo de python que ofrece una librería para graficar.
En general viene instalado con la distribución de python Anaconda, y si no se
puede instalar con el comando ``pip``:
.. code::
pip install -U matplotlib
Si eso no funciona, `consultar los detalles de la documentación `_.
Una vez instalado, se puede acceder al módulo desde un entorno de python (es
decir, luego de "entrar" a python) con el comando import:
.. code:: python
import matplotlib
aunque no es muy usual utilizarlo así.
Interface pyplot
========================
El módulo Matplotlib incluye una interface denominada ``pyplot`` que tiene todas las
herramientas para hacer gráficos sencillos. Es posible que resulte un poco
confuso la utilización de términos como módulo, librería o interface, pero no es
necesario tener un conocimiento acabado de estos conceptos para producir
gráficos, ni está en el alcance de esta materia. En este breve tutorial
aprenderemos lo básico para realizar gráficos aprendiendo a partir de ejemplos.
Para cargar esta interface, simplemente usamos el comando import:
.. code:: python
import matplotlib.pyplot
Hay otras formas de hacer lo mismo, que se pueden encontrar en los numerosos
tutoriales que hay disponibles en internet. Algunas de estas formas son:
.. code:: python
from matplotlib import pyplot # (alternativa 1)
from matplotlib import pyplot as plt # (alternativa 2)
import matplotlib.pyplot as plt # (alternativa 3)...
Esas tres líneas son equivalentes (sólo hay que usar una). Notar que se
introdujo el alias ``plt``, que es una costumbre muy arraigada en la comunidad de
ciencias de datos. Se puede reemplazar ``plt`` por cualquier otra cosa. En lo
que sigue usaremos el alias ``plt`` como es usual.
Estilos de uso para pyplot
===========================
Antes de empezar a hacer gráficos, conviene aclarar que hay dos formas de usar
``Pyplot``. Puede ser confuso leer la documentación disponible si no se tiene en
cuenta esto, ya que las mismas cosas sencillas se encuentran realizadas de
diferentes formas. Esta sección está destinada a evitar esas confusiones al
mostrar las dos formas de trabajo, que son:
* estilo matlab
* estilo con orientación a objetos
Para el práctico se puede usar cualquiera de las dos.
Pyplot al estilo Matlab
-----------------------
Esta forma de usar Pyplot se llama "sintaxis imperativa", y fue diseñada
para parecerse a Matlab, que es otro lenguaje pensado para trabajar con matrices
que permite también hacer gráficos.
El gráfico de la función seno en Matlab se puede hacer así:
.. code:: matlab
x = linspace(0,2*pi,100);
y = sin(x);
plot(x,y)
xlabel('x')
ylabel('sin(x)')
title('Grafico de la funcion seno')
Ahora hacemos el mismo gráfico desde python:
.. code-block:: python
:linenos:
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('sin(x)')
plt.title('Grafico de la funcion seno')
plt.show()
En la línea 6 estamos creando un gráfico a partir de los arrays x e y, y a
partir de allí todo lo que hacemos con ``plt`` se aplica a ese gráfico.
Al usar el método ``pylab`` (ver más adelante), es posible modificar los atributos de los
gráficos de manera interactiva e ir visualizando los cambios. En ese
caso no se usa ``plt.`` sino que se escribe directamente la función,
de manera similar a Matlab:
.. code-block:: python
# luego de entrar al interprete usando ipython --pylab:
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plot(x, y)
xlabel('x')
ylabel('sin(x)')
title('Grafico de la funcion seno')
alternativamente,
.. code-block:: python
# luego de entrar al interprete usando ipython --pylab:
import numpy as np
from pylab import *
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plot(x, y)
xlabel('x')
ylabel('sin(x)')
title('Grafico de la funcion seno')
show()
notar que en este último ejemplo importamos todas las funciones del módulo ``pylab``. Aquí el gráfico no será interactivo.
Pyplot al estilo Orientación a Objetos
--------------------------------------
La orientación a objetos es un paradigma de programación (es decir, una forma de
programar justificada teóricamente) que permite estructurar el código utilizando
objetos que tienen propiedades o comportamientos. Por ejemplo, un objeto de
tipo "animal" puede moverse de cierta forma, como caminar o nadar
(comportamiento o método) o tener cierta cantidad de patas (propiedad).
Los comportamientos se implementan mediante funciones y se llaman
"métodos".
Para ilustrar de modo genérico y sin formalidad cómo funciona esto, pensemos en definir
un objeto de tipo animal que tiene la propiedad de moverse:
.. code-block:: python
oveja = animal()
movimiento = oveja.movimiento()
Un programa
puede tener varios objetos de tipo "animal" y no hace falta programar cada uno,
sino que basta con decir que "es un animal" y fácilmente adquiere la propiedad
de "número de patas" o el comportamiento de "forma de moverse".
Para hacer gráficos usando este concepto, trabajamos con dos objetos:
1. el objeto ``figure``, que es la figura y puede contener varios gráficos (o
``axes``)
2. el objeto ``axes``, que es la región que contiene un gráfico individual. No es
lo mismo que los ejes (x/y axis).
Así, por ejemplo, siguiendo la idea del ejemplo anterior, podremos
hacer cosas como esta:
.. code-block:: python
# plt puede crear una figura
figura = plt.figure()
# el objeto figura puede crear un area de trazado
ejes = figura.add_subplot()
# los ejes pueden adoptar nombres
ejes.set_xlabel('eje X')
ejes.set_ylabel('eje Y')
# o pueden pasarse a escala logaritmica
ejes.set_xscale('log')
Allí por ejemplo el método del objeto ``figura`` que crea los ejes se llama
``add_subplot`` y el método del objeto ``ejes`` que le permite da un
nombre al eje X se llama ``set_xlabel``. Es costumbre en la comunidad
de python llamarle ``fig`` a una figura y ``ax`` (o ``axes``) al area de trazado.
En la siguiente figura se muestran
estos dos elementos, además de otros que usaremos para personalizar el aspecto
visual del gráfico. Figure se refiere a toda la figura, y axes a la parte
interior del sistema de ejes.
.. image:: partes_del_plot.png
:width: 600px
:align: center
:alt: Elementos de un gráfico
Es posible encontrar más detalles en `esta otra versión `_.
Para generar una gráfico usando objetos, hay que crear un objeto de tipo ``figure``, y luego un objeto de tipo ``axes``, que es donde se realizará el gráfico.
.. code-block:: python
:linenos:
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
fig = plt.figure()
fig.clf()
ax = fig.add_subplot(1,1,1)
ax.clear()
ax.plot(x, y)
ax.set_xlabel('x')
ax.set_ylabel('sin(x)')
ax.set_title('Grafico de la funcion seno')
fig.show()
aquí la función ``figure`` de pyplot crea una nueva figura, que está almacenada en
el objeto ``fig``. Este objeto, que es de tipo figura, puede hacer ciertas cosas,
por ejemplo limpiar (``.clear()``) o mostrar (``.show()``) la figura. Otra cosa que se puede hacer es crear un
objeto de tipo ``axes``, lo cual se hace en la línea 9 con la función
``add_subplot``.
Notar que add_subplot tiene 3 argumentos, para saber qué son podemos
acceder a la ayuda en la documentación, por ejemplo
desde el intérprete de ``ipython``, haciendo:
.. code::
from matplotlib import pyplot as plt
fig = plt.figure()
fig.add_subplot?
Hay otras formas de usar los objetos ``figure`` y ``axes``,
por ejemplo usando la función ``subplots`` de
Pyplot, que devuelve tanto la figura como los gráficos (``axes``) que contiene:
.. code-block:: python
:linenos:
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_xlabel('x')
ax.set_ylabel('sin(x)')
ax.set_title('Grafico de la funcion seno')
fig.show()
Si quisiéramos hacer una figura con más de un gráfico, se usan los parámetros de
``add_subplot`` o de ``subplots`` (de nuevo, ver la ayuda). Por ejemplo, para hacer los
gráficos de las funciones seno y coseno, uno al lado del otro:
.. code-block:: python
:linenos:
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(0, 2*np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)
fig, ax = plt.subplots(1, 2)
ax[0].plot(x, y1)
ax[0].set_xlabel('x')
ax[0].set_ylabel('sin(x)')
ax[0].set_title('Grafico de la funcion seno')
ax[1].plot(x, y2)
ax[1].set_xlabel('x')
ax[1].set_ylabel('cos(x)')
ax[1].set_title('Grafico de la funcion coseno')
fig.show()
Notar que ``subplots`` devuelve un objeto axes que es una lista, donde cada elemento
es un gráfico, es decir, ``ax[0]`` es el gráfico de la izquierda y ``ax[1]`` es el
gráfico de la derecha. Al graficar, hay que decir en cuál de esos dos gráficos
estamos trabajando.
Para hacer los dos gráficos, pero uno arriba del otro, sólo hay que cambiar los
parámetros de ``plt.subplots`` (queda como ejercicio).
Otra forma de trabajar que se puede encontrar en los recursos
destinados a este tema y que también es orientada a objetos, consiste
en guardar el gráfico como un objeto. Por ejemplo, al graficar una
línea guardamos el objeto de tipo "línea" (``matplotlib.lines.Line2D``).
Luego a este objeto lo podemos modificar usando las funciones "set",
por ejemplo:
.. code-block:: python
:linenos:
import matplotlib.pyplot as plt
f = plt.figure()
ax = f.add_subplot()
l, = ax.plot([1,2,3],[5,3,5])
l.set_color('tomato')
l.set_linestyle('--')
l.set_linewidth(3)
l.set_marker('o')
l.set_markeredgecolor('o')
l.set_markeredgewidth('o')
l.set_markerfacecolor('o')
plt.show()
Obteniendo el gráfico
--------------------------------------
Dependiendo de la forma de trabajar, necesitaremos hacer distintas cosas para
obtener o visualizar el gráfico.
Se pueden mencionar las siguientes alternativas para trabajar en un
entorno de python y visualizar el resultado de un gráfico con
matplotlib:
1. Visualización en pantalla
Para visualizar un gráfico en pantalla hay que pedirlo explícitamente con el método ``show`` de ``pyplot``.
.. code-block:: python
plt.show()
2. Gráficos interactivos
Se puede interactuar con un gráfico entrando al intérprete de ipython
con la opción --pylab:
.. code::
$ ipython --pylab
Notar que aquí el símbolo "$" corresponde al prompt del sistema.
3. Utilizando Notebooks
Los notebooks son herramientas interactivas que corren en un
navegador y que permiten combinar elementos de varios tipos, tales
como gráficos, markdown, código y latex.
Para ver los gráficos, en una celda del notebook hay que escribir el
comando:
.. code-block:: python
%matplotlib inline
El programa para trabajar con notebooks más usado en `Jupyter `_.
4. Salida a un archivo
Hay que guardar el gráfico en un archivo, con el método ``savefig``
de una figura.
.. code-block:: python
fig.savefig('MiFigura.png')
Más detalles se pueden encontrar `por ejemplo aquí `_
Los formatos más usados son PNG, PDF y SVG. Para más información
se puede consultar la documentación de `savefig `_.
5. Entornos de desarrollo integrado
Existen muchos programas que permiten desarrollar códigos y
graficar en el mismo entorno. Algunos de los que se pueden
mencionar son:
* `Spyder `_
* `PyCharm `_
* `VSC `_
Gráficos simples
========================
Ahora veremos ejemplos simples de cómo hacer gráficos en python usando
matplotlib. Existen varios tipos de gráficos que se pueden hacer, los
más simples son:
+----------------------+-------------------------------------+
| Tipo de gráfico | ejemplo |
+======================+=====================================+
| lineas | .. image:: line.png |
| | :width: 300px |
| | :align: center |
+----------------------+-------------------------------------+
| puntos (scatter) | .. image:: scatter.png |
| | :width: 300px |
| | :align: center |
+----------------------+-------------------------------------+
| barras | .. image:: bars.png |
| | :width: 300px |
| | :align: center |
+----------------------+-------------------------------------+
| histograma | .. image:: hist.png |
| | :width: 300px |
| | :align: center |
+----------------------+-------------------------------------+
Hay muchos otros, pero entendiendo estos pocos se puede fácilmente
incursionar en otros tipos de gráfico usando la documentación.
Varios gráficos en la misma figura
-----------------------------------
Para hacer varios gráficos en la misma figura se puede usar, como
vimos, las funciones ``subplots`` o ``add_subplot``.
.. code-block:: python
from matplotlib import pyplot as plt
x = np.linspace(-10, 10, 100)
y1 = x
y2 = x**2
y3 = x**3
y4 = x**4
fig = plt.figure()
fig.clf()
ax = fig.subplots(2,2)
ax[0,0].plot(x, y1)
ax[0,0].set_xlabel('x')
ax[0,0].set_ylabel('y')
ax[0,0].set_title('y=x**1')
ax[0,1].plot(x, y2)
ax[0,1].set_xlabel('x')
ax[0,1].set_ylabel('y')
ax[0,1].set_title('y=x**2')
ax[1,0].plot(x, y3)
ax[1,0].set_xlabel('x')
ax[1,0].set_ylabel('y')
ax[1,0].set_title('y=x**3')
ax[1,1].plot(x, y4)
ax[1,1].set_xlabel('x')
ax[1,1].set_ylabel('y')
ax[1,1].set_title('y=x**4')
fig.tight_layout()
fig.show()
Que da algo así:
.. image:: 4x4.png
:width: 400px
:align: center
También se puede usar la función ``add_axes``, que hace lo mismo pero
tiene una sintaxis un poco diferente, ya que permite elegir
explícitamente el tamaño y la ubicación de los gráficos.
Los argumentos de `add_axes `_ son las coordenadas de la esquina inferior izquierda del gráfico, y los tamaños de los ejes en el gráfico.
Ver por ejemplo qué produce el siguiente código:
.. code-block:: python
f = plt.figure()
ax1 = f.add_axes([.1, .1, .85, .6])
ax2 = f.add_axes([.8, .8, .18, .18])
ax3 = f.add_axes([.2, .2, .5, .1])
ax1.set_xlim([0, 1000])
ax3.set_ylim([0.1, 0.3])
plt.show()
Varias lineas en el mismo grafico
-----------------------------------
Para graficar varias series de datos en el mismo gráfico
se puede llamar a una función que grafique varias veces.
Por ejemplo, si queremos graficar las funciones seno y coseno en el
mismo gráfico, podemos proceder así:
.. code-block:: python
from matplotlib import pyplot as plt
x = np.linspace(-1, 1, 100)
y1 = x
y2 = x**2
y3 = x**3
y4 = x**4
fig = plt.figure()
fig.clf()
ax = fig.subplots(1,1)
ax.plot(x, y1, label='y=x**1')
ax.plot(x, y2, label='y=x**2')
ax.plot(x, y3, label='y=x**3')
ax.plot(x, y4, label='y=x**4')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend()
fig.tight_layout()
fig.show()
Que da algo así:
.. image:: 1x1.png
:width: 400px
:align: center
Atributos de los ejes
-----------------------------------
Se pueden modificar los atributos de los ejes, para lo cual primero
hay que identificar los diferentes elementos. Las líneas de los ejes
que marcan los valores de la escala se llaman ``ticks``, cada tick
tiene una valor, que está dentro de un rango determinado.
Comencemos con el siguiente gráfico simple y tratemos de mejorarlo un
poco:
.. code-block:: python
fig, ax = plt.subplots()
N = 500
x = np.random.rand(N)
y = np.random.rand(N)
plt.scatter(x, y)
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
.. image:: simple.png
:width: 600px
:align: center
Queremos cambiar la apariencia del texto usado para etiquetar
(``labels``) las lineas que marcan la escala (``ticks``).
Esto es común porque en general hace falta agrandar la fuente del
texto para que el gráfico sea legible al ser mostrado en distintos
medios (por ej. una presentación). Usaremos las siguientes funciones
de
.. code-block:: python
fig, ax = plt.subplots()
N = 500
x = np.random.rand(N)
y = np.random.rand(N)
plt.scatter(x, y)
ax.set_xlabel('x', fontsize=16)
ax.set_ylabel('y', fontsize=16)
ticks = [.2, .4, .6, .8]
labels = ['0.2', '0.4', '0.6', '0.8']
ax.set_xticks(ticks=ticks)
ax.set_xticklabels(labels=labels, fontsize=16)
ax.set_yticks(ticks=ticks)
ax.set_yticklabels(labels=labels, fontsize=16)
ax.tick_params(axis='x', direction='in', length=8, color='slategrey')
ax.tick_params(axis='y', direction='in', length=8)
plt.show()
.. image:: tunned.png
:width: 600px
:align: center
Atributos de las series de datos
-----------------------------------
Ahora tratemos de mejorar el contenido de los plots. Hay muchos
atributos para trabajar, los más comunes son:
+------------------------+----------------------------+--------------------------------------------------+
| atributo | modifica | opciones |
+========================+============================+==================================================+
| alpha | transparencia | escalar |
+------------------------+----------------------------+--------------------------------------------------+
| color or c | color | color de matplotlib |
+------------------------+----------------------------+--------------------------------------------------+
| label | etiqueta | cadena de carateres |
+------------------------+----------------------------+--------------------------------------------------+
| linestyle or ls | tipo de linea | ``[ '-' | '--' | '-.' | ':' | 'steps' | ...]`` |
+------------------------+----------------------------+--------------------------------------------------+
| linewidth or lw | ancho de linea | escalar |
+------------------------+----------------------------+--------------------------------------------------+
| marker | marcador | ``[ '+' | ',' | '.' | '1' | '2' | '3' | '4' ]`` |
+------------------------+----------------------------+--------------------------------------------------+
| markeredgecolor or mec | color de borde de marcador | color de matplotlib |
+------------------------+----------------------------+--------------------------------------------------+
| markeredgewidth or mew | grosor del marcador | escalar |
+------------------------+----------------------------+--------------------------------------------------+
| markerfacecolor or mfc | color de relloeno marcador | color de matplotlib |
+------------------------+----------------------------+--------------------------------------------------+
| markersize or ms | tamaño del marcador | escalar |
+------------------------+----------------------------+--------------------------------------------------+
| markevery | un marcador cada... | entero |
+------------------------+----------------------------+--------------------------------------------------+
Entre los colores de Matplotlib, los más comunes se pueden usar con nombre:
.. image:: colors.png
:width: 800px
:align: center
Veamos ahora algunos gráficos donde hemos cambiado varios atributos.
La sintaxis es bastante simpĺe y es posible entender cómo funciona
leyendo el código:
.. code-block:: python
fig, ax = plt.subplots()
N = 500
x = np.random.rand(N)
y = np.random.rand(N)
plt.scatter(x, y, s=44, color='cadetblue', alpha=0.6)
ax.set_xlabel('x', fontsize=16)
ax.set_ylabel('y', fontsize=16)
ticks = [.2, .4, .6, .8]
labels = ['0.2', '0.4', '0.6', '0.8']
ax.set_xticks(ticks=ticks)
ax.set_xticklabels(labels=labels, fontsize=16)
ax.set_yticks(ticks=ticks)
ax.set_yticklabels(labels=labels, fontsize=16)
ax.tick_params(axis='x', direction='in', length=8, color='slategrey')
ax.tick_params(axis='y', direction='in', length=8)
plt.tight_layout()
plt.show()
.. image:: evenbetter.png
:width: 800px
:align: center
o con líneas:
.. code-block:: python
from matplotlib import pyplot as plt
x = np.linspace(-1, 1, 100)
y1 = x
y2 = x**2
y3 = x**3
y4 = x**4
fig = plt.figure()
fig.clf()
ax = fig.subplots(1,1)
ax.plot(x, y1, color='cornflowerblue', linewidth=2, label='y=x')
ax.plot(x, y2, color='limegreen', linewidth=2, label='y=x^2')
ax.plot(x, y3, color='tomato', linewidth=2, label='y=x^3')
ax.plot(x, y4, color='darkorchid', linewidth=2, label='y=x^4')
ticks = [(-1.0 + 0.5*i) for i in range(5)]
labels = [f"{s: 2.1f}" for s in ticks]
ax.set_xticks(ticks=ticks)
ax.set_xticklabels(labels=labels, fontsize=16)
ax.set_yticks(ticks=ticks)
ax.set_yticklabels(labels=labels, fontsize=16)
ax.set_xlabel('x', fontsize=22)
ax.set_ylabel('y', fontsize=22)
ax.legend(loc='lower right', frameon=false,
borderaxespad=4,
ncol=2, handlelength=3)
ax.xaxis.label.set_size(16)
fig.tight_layout()
fig.show()
.. image:: evenbetter2.png
:width: 800px
:align: center
Por último veamos cómo modificar las líneas incluyendo marcadores. El
siguiente código implementa varios tipos de marcadores para mostrar
cómo se usa. No están explicados en detalles, pero habiendo seguido
este tutorial es fácil buscar cómo se usan e incluso explorar muchas
más opciones para graficar.
.. code-block:: python
from matplotlib import pyplot as plt
import numpy as np
x = np.linspace(-1, 1, 100)
y1 = x
y2 = x**2
y3 = x**3
y4 = x**4
fig = plt.figure()
fig.clf()
ax = fig.subplots(1,1)
ax.plot(x, y1, color='cornflowerblue', linewidth=2, label='y=x',
linestyle='-', marker='o', markerfacecolor='white',
markeredgewidth=1, markersize=6, markevery=10, alpha=1)
ax.plot(x, y2, color='limegreen', linewidth=2, label='y=x^2',
linestyle='--', marker='D', markerfacecolor='limegreen',
markeredgewidth=1, markersize=6, markevery=10, alpha=1)
ax.plot(x, y3, color='tomato', linewidth=2, label='y=x^3',
linestyle='-', marker='s', markerfacecolor='white',
markeredgewidth=1, markersize=6, markevery=10, alpha=1)
ax.plot(x, y4, color='darkorchid', linewidth=1, label='y=x^4',
linestyle='-', marker='o', markerfacecolor='darkorchid',
markeredgewidth=1, markersize=3, markevery=10, alpha=1)
ticks = [(-1.0 + 0.5*i) for i in range(5)]
labels = [f"{s: 2.1f}" for s in ticks]
ax.set_xticks(ticks=ticks)
ax.set_xticklabels(labels=labels, fontsize=16)
ax.set_yticks(ticks=ticks)
ax.set_yticklabels(labels=labels, fontsize=16)
ax.set_xlabel('x', fontsize=22)
ax.set_ylabel('y', fontsize=22)
ax.legend(loc='lower right', frameon=False,
borderaxespad=4,
ncol=2, handlelength=3)
ax.xaxis.label.set_size(16)
fig.tight_layout()
fig.show()
.. image:: markers.png
:width: 800px
:align: center
.. `backends `._
Gramática de gráficos con plotnine
====================================
Una forma natural de hacer gráficos es mediante el "diseño orientado a
objetos", que se describe en el libro `"The grammar of graphics", de L.
Wilkinson, 2005, Springer-Verlag, New York `_.
Las ideas de este libro están implementadas en una librería de R muy
popular, que se llama `ggplot2 `_.
Existe una versión para python, denominada `plotnine `_. Este paquete permite hacer gráficos complejos con muchas menos líneas de código comparado por ejemplo con matplotlib.
Supongamos por ejemplo que tenemos datos de vehículos, y queremos
graficar el rendimiento del combustible en función del peso,
diferenciando según la cantidad de marchas:
.. image:: readme-image-4.png
:width: 600px
:align: center
:alt: Gráfico de vehículos (tomado de https://plotnine.readthedocs.io/en/stable/index.html)
Este gráfico se puede hacer con la siguiente idea:
* tengo los todos datos en una tabla
* elijo los datos que quiero graficar
* elijo la estética
* agrego un ajuste lineal con su error
la implementación es la siguiente:
.. code-block:: python
from plotnine import ggplot, geom_point, aes, stat_smooth, facet_wrap
from plotnine.data import mtcars
(ggplot(mtcars, aes('wt', 'mpg', color='factor(gear)'))
+ geom_point()
+ stat_smooth(method='lm')
+ facet_wrap('~gear'))
De esta forma el gráfico está hecho en "capas". Veamos esto más en
detalle:
1. Con ggplot se crea una instancia de un gráfico. Los argumentos de
ggplot con la fuente de datos y la selección de los datos a
graficar::
ggplot(mtcars, aes('wt', 'mpg', color='factor(gear)'))
2. Una vez que se seleccionaron los datos, hay que elegir un atributo
gráfico con el cual se quieren representar. Por ejemplo, con
puntos::
estilo = geom_point()
3. Se puede agregar algún análisis estadístico. Por ejemplo un ajuste
lineal::
stats = stat_smooth(method='lm')
4. Y finalmente, elegimos separar los gráficos según la cantidad de
marchas::
paneles = facet_wrap('~gear')
Esto ultimo se llama "faceting". Ahora se puede rehacer el gráfico de una forma más evidente:
.. code-block:: python
from plotnine import ggplot, geom_point, aes, stat_smooth, facet_wrap
from plotnine.data import mtcars
plot = ggplot(mtcars, aes('wt', 'mpg', color='factor(gear)'))
estilo = geom_point()
stats = stat_smooth(method='lm')
paneles = facet_wrap('~gear')
plot + estilo + stats + paneles
Se puede probar agregar o sacar capas, por ejemplo::
plot + estilo
hace el gráfico sin las estadísticas y en un solo panel. Se puede
agregar o sacar el ajuste de la recta y poner en paneles o no::
plot + estilo + stats
# o bien:
plot + estilo + paneles
Para dar otro ejemplo, supongamos que queremos
estudiar relaciones en los parámetros de una base de
datos de planetas extrasolares. El siguiente gráfico es un gráfico
de dispersión del radio vs. el semieje mayor de la órbita de un
conjunto de exoplanetas, donde el color indica el periodo y el tamaño
de los puntos la masa*sin(i).
.. code-block:: python
D=pd.read_csv('planets.csv')
axes = aes('pl_orbsmax','pl_radj',color='pl_orbper')
points = geom_point(aes(size='pl_bmassj'), alpha=0.5)
plt = ggplot(D, axes) + points
plt + scales.scale_x_log10() + scales.scale_y_log10()
.. image:: Figure_1.png
:width: 600px
:align: center
:alt: Exoplanetas
Resources:
`Clearing the confusion once and for all: fig, ax = plt.subplots()`_
`Python for astronomers: plotting `_