El ciclo de vida de una parcela #

Este tutorial tiene como objetivo mostrar el principio, el medio y el final de una sola visualización usando Matplotlib. Comenzaremos con algunos datos sin procesar y terminaremos guardando una figura de una visualización personalizada. En el camino, tratamos de resaltar algunas características interesantes y mejores prácticas usando Matplotlib.

Nota

Este tutorial se basa en esta excelente publicación de blog de Chris Moffitt. Fue transformado en este tutorial por Chris Holdgraf.

Una nota sobre las interfaces explícitas frente a las implícitas #

Matplotlib tiene dos interfaces. Para obtener una explicación de las compensaciones entre las interfaces explícitas e implícitas, consulte Interfaces de aplicaciones (API) de Matplotlib .

En la interfaz explícita orientada a objetos (OO), utilizamos directamente instancias de axes.Axespara construir la visualización en una instancia de figure.Figure. En la interfaz implícita, inspirada y modelada en MATLAB, utiliza una interfaz global basada en el estado que está encapsulada en el pyplotmódulo para trazar los "Ejes actuales". Consulte los tutoriales de pyplot para obtener una visión más detallada de la interfaz de pyplot.

La mayoría de los términos son sencillos, pero lo más importante que debe recordar es que:

  • La Figura es la imagen final que puede contener 1 o más Ejes.

  • Los ejes representan un gráfico individual (no confunda esto con la palabra "eje", que se refiere al eje x/y de un gráfico).

Llamamos métodos que trazan directamente desde los Ejes, lo que nos da mucha más flexibilidad y poder para personalizar nuestra trama.

Nota

En general, prefiera la interfaz explícita sobre la interfaz pyplot implícita para trazar.

Nuestros datos #

Usaremos los datos de la publicación de la que se derivó este tutorial. Contiene información de ventas de varias empresas.

import numpy as np
import matplotlib.pyplot as plt


data = {'Barton LLC': 109438.50,
        'Frami, Hills and Schmidt': 103569.59,
        'Fritsch, Russel and Anderson': 112214.71,
        'Jerde-Hilpert': 112591.43,
        'Keeling LLC': 100934.30,
        'Koepp Ltd': 103660.54,
        'Kulas Inc': 137351.96,
        'Trantow-Barrows': 123381.38,
        'White-Trantow': 135841.99,
        'Will LLC': 104437.60}
group_data = list(data.values())
group_names = list(data.keys())
group_mean = np.mean(group_data)

Empezando #

Estos datos se visualizan naturalmente como un gráfico de barras, con una barra por grupo. Para hacer esto con el enfoque orientado a objetos, primero generamos una instancia de figure.Figurey axes.Axes. La Figura es como un lienzo, y los Ejes son una parte de ese lienzo sobre el cual realizaremos una determinada visualización.

Nota

Las figuras pueden tener múltiples ejes sobre ellas. Para obtener información sobre cómo hacer esto, consulte el tutorial Diseño ajustado .

fig, ax = plt.subplots()
ciclo vital

Ahora que tenemos una instancia de Axes, podemos trazar sobre ella.

ciclo vital
<BarContainer object of 10 artists>

Controlando el estilo #

Hay muchos estilos disponibles en Matplotlib para permitirle adaptar su visualización a sus necesidades. Para ver una lista de estilos, podemos usar style.

['Solarize_Light2', '_classic_test_patch', '_mpl-gallery', '_mpl-gallery-nogrid', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'seaborn-v0_8', 'seaborn-v0_8-bright', 'seaborn-v0_8-colorblind', 'seaborn-v0_8-dark', 'seaborn-v0_8-dark-palette', 'seaborn-v0_8-darkgrid', 'seaborn-v0_8-deep', 'seaborn-v0_8-muted', 'seaborn-v0_8-notebook', 'seaborn-v0_8-paper', 'seaborn-v0_8-pastel', 'seaborn-v0_8-poster', 'seaborn-v0_8-talk', 'seaborn-v0_8-ticks', 'seaborn-v0_8-white', 'seaborn-v0_8-whitegrid', 'tableau-colorblind10']

Puede activar un estilo con lo siguiente:

plt.style.use('fivethirtyeight')

Ahora rehagamos el gráfico anterior para ver cómo se ve:

ciclo vital
<BarContainer object of 10 artists>

El estilo controla muchas cosas, como el color, el ancho de línea, los fondos, etc.

Personalizando la trama #

Ahora tenemos un gráfico con el aspecto general que queremos, así que afinémoslo para que esté listo para imprimir. Primero, giremos las etiquetas en el eje x para que se vean más claramente. Podemos acceder a estas etiquetas con el axes.Axes.get_xticklabels()método:

ciclo vital

Si deseamos establecer la propiedad de muchos elementos a la vez, es útil usar la pyplot.setp()función. Esto tomará una lista (o muchas listas) de objetos Matplotlib e intentará establecer algún elemento de estilo de cada uno.

fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ciclo vital
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]

Parece que esto cortó algunas de las etiquetas en la parte inferior. Podemos decirle a Matplotlib que haga espacio automáticamente para los elementos en las figuras que creamos. Para ello establecemos el autolayoutvalor de nuestro rcParams. Para obtener más información sobre cómo controlar el estilo, el diseño y otras características de los gráficos con rcParams, consulte Personalización de Matplotlib con hojas de estilo y rcParams .

plt.rcParams.update({'figure.autolayout': True})

fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ciclo vital
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]

A continuación, agregamos etiquetas a la trama. Para hacer esto con la interfaz OO, podemos usar el Artist.set()método para establecer las propiedades de este objeto Axes.

fig, ax = plt.subplots()
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue')
Ingresos de la empresa
[(-10000.0, 140000.0), Text(0.5, 87.00000000000003, 'Total Revenue'), Text(86.99999999999997, 0.5, 'Company'), Text(0.5, 1.0, 'Company Revenue')]

También podemos ajustar el tamaño de este gráfico usando la pyplot.subplots() función. Podemos hacer esto con el argumento de la palabra clave figsize .

Nota

Mientras que la indexación en NumPy sigue el formulario (fila, columna), el argumento de la palabra clave figsize sigue el formulario (ancho, alto). Esto sigue las convenciones de visualización, que desafortunadamente son diferentes de las del álgebra lineal.

fig, ax = plt.subplots(figsize=(8, 4))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')
ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue')
Ingresos de la empresa
[(-10000.0, 140000.0), Text(0.5, 86.99999999999997, 'Total Revenue'), Text(86.99999999999997, 0.5, 'Company'), Text(0.5, 1.0, 'Company Revenue')]

Para las etiquetas, podemos especificar pautas de formato personalizadas en forma de funciones. A continuación, definimos una función que toma un número entero como entrada y devuelve una cadena como salida. Cuando se usan con Axis.set_major_formattero Axis.set_minor_formatter, automáticamente crearán y usarán una ticker.FuncFormatterclase.

Para esta función, el xargumento es la etiqueta de marca original y pos es la posición de marca. Solo usaremos xaquí, pero ambos argumentos son necesarios.

def currency(x, pos):
    """The two arguments are the value and tick position"""
    if x >= 1e6:
        s = '${:1.1f}M'.format(x*1e-6)
    else:
        s = '${:1.0f}K'.format(x*1e-3)
    return s

Luego podemos aplicar esta función a las etiquetas en nuestra gráfica. Para hacer esto, usamos el xaxisatributo de nuestros ejes. Esto le permite realizar acciones en un eje específico en nuestra trama.

fig, ax = plt.subplots(figsize=(6, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')

ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
Ingresos de la empresa

Combinando múltiples visualizaciones #

Es posible dibujar múltiples elementos de la trama en la misma instancia de axes.Axes. Para hacer esto, simplemente necesitamos llamar a otro de los métodos de trazado en ese objeto de ejes.

fig, ax = plt.subplots(figsize=(8, 8))
ax.barh(group_names, group_data)
labels = ax.get_xticklabels()
plt.setp(labels, rotation=45, horizontalalignment='right')

# Add a vertical line, here we set the style in the function call
ax.axvline(group_mean, ls='--', color='r')

# Annotate new companies
for group in [3, 5, 8]:
    ax.text(145000, group, "New Company", fontsize=10,
            verticalalignment="center")

# Now we move our title up since it's getting a little cramped
ax.title.set(y=1.05)

ax.set(xlim=[-10000, 140000], xlabel='Total Revenue', ylabel='Company',
       title='Company Revenue')
ax.xaxis.set_major_formatter(currency)
ax.set_xticks([0, 25e3, 50e3, 75e3, 100e3, 125e3])
fig.subplots_adjust(right=.1)

plt.show()
Ingresos de la empresa

Guardando nuestra parcela #

Ahora que estamos satisfechos con el resultado de nuestro diagrama, queremos guardarlo en el disco. Hay muchos formatos de archivo en los que podemos guardar en Matplotlib. Para ver una lista de opciones disponibles, utilice:

{'eps': 'Encapsulated Postscript', 'jpg': 'Joint Photographic Experts Group', 'jpeg': 'Joint Photographic Experts Group', 'pdf': 'Portable Document Format', 'pgf': 'PGF code for LaTeX', 'png': 'Portable Network Graphics', 'ps': 'Postscript', 'raw': 'Raw RGBA bitmap', 'rgba': 'Raw RGBA bitmap', 'svg': 'Scalable Vector Graphics', 'svgz': 'Scalable Vector Graphics', 'tif': 'Tagged Image File Format', 'tiff': 'Tagged Image File Format', 'webp': 'WebP Image Format'}

Luego podemos usar el figure.Figure.savefig()para guardar la figura en el disco. Tenga en cuenta que hay varias banderas útiles que mostramos a continuación:

  • transparent=Truehace que el fondo de la figura guardada sea transparente si el formato lo admite.

  • dpi=80controla la resolución (puntos por pulgada cuadrada) de la salida.

  • bbox_inches="tight"ajusta los límites de la figura a nuestra gráfica.

# Uncomment this line to save the figure.
# fig.savefig('sales.png', transparent=False, dpi=80, bbox_inches="tight")

Tiempo total de ejecución del script: (0 minutos 3,918 segundos)

Galería generada por Sphinx-Gallery