Capítulo 11 Pyplot
Una primera forma en la que matplotlib puede ser programada es Pyplot, la cual inicialmente imitó a MATLAB y utiliza una interfaz basada en estados, es decir, cada función de pyplot realiza algún cambio en una figura: por ejemplo, crea una figura, crea un área de trazado en una figura, traza algunas líneas en un área de trazado, decora el trazado con etiquetas, etc.
Es la opción indicada cuando se desea realizar un análisis exploratorio de unos datos, pero puede llegar a crearse una buena visualización.
Se caracteriza en que parte de un lienzo y unos ejes de coordenadas “actuales”, es decir, sobre los que se está trabajando.
Obsérvense las posibilidades.
En primer lugar, generar un lienzo:

Añádanse algunos datos:

La asignación fantasma de _ = se realiza para evitar que se añadan mensajes desde el compilador de python. Se debe a que se está generando este código en python en un ambiente interactivo desde RStudio, con una traductor de python mediante el paquete reticulate. En otras IDE no es necesario, así que pueden evitar dicha asignación fantasma.
Ahora unas marcas:

Hay muchos otros marcadores
# plt.plot(x,y, marker='.')
# plt.plot(x,y, marker='>')
plt.plot(x,y, marker='^')
# plt.plot(x,y, marker='1')
Encuentre una lista completa en este enlace.
Estilos de línea:
# plt.plot(x,y, marker='o', linestyle = '--')
_ = plt.plot(x,y, marker='o', linestyle = '-.')
# plt.plot(x,y, marker='o', linestyle = ':')
Pruebe uno a uno y determine la lógica de su simbología.
En vez del símbolo puede ser explícito y colocar ‘solid’, ‘dashed’, ‘dashdot’ ó ‘dotted’. Vea una lista para más personalización.
No hace falta escribir el argumento linestyle. Pyplot toma el tercer argumento como una concatenación del color y el estilo de la línea:

Las líneas tienen muchos atributos que se pueden establecer: ancho de línea, estilo de guiones, anti-solapamiento (antialiasing), etc. Hay varias formas de establecer las propiedades de las líneas:
Nombrando los argumentos:

Utilizando métodos de establecimiento de una instancia de un objeto line2D.
Para obtener una lista de las propiedades de las líneas que se pueden configurar, llame a la función setp con una o varias líneas como argumento:
## agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array and two offsets from the bottom left corner of the image
## alpha: scalar or None
## animated: bool
## antialiased or aa: bool
## clip_box: `~matplotlib.transforms.BboxBase` or None
## clip_on: bool
## clip_path: Patch or (Path, Transform) or None
## color or c: :mpltype:`color`
## dash_capstyle: `.CapStyle` or {'butt', 'projecting', 'round'}
## dash_joinstyle: `.JoinStyle` or {'miter', 'round', 'bevel'}
## dashes: sequence of floats (on/off ink in points) or (None, None)
## data: (2, N) array or two 1D arrays
## drawstyle or ds: {'default', 'steps', 'steps-pre', 'steps-mid', 'steps-post'}, default: 'default'
## figure: `~matplotlib.figure.Figure`
## fillstyle: {'full', 'left', 'right', 'bottom', 'top', 'none'}
## gapcolor: :mpltype:`color` or None
## gid: str
## in_layout: bool
## label: object
## linestyle or ls: {'-', '--', '-.', ':', '', (offset, on-off-seq), ...}
## linewidth or lw: float
## marker: marker style string, `~.path.Path` or `~.markers.MarkerStyle`
## markeredgecolor or mec: :mpltype:`color`
## markeredgewidth or mew: float
## markerfacecolor or mfc: :mpltype:`color`
## markerfacecoloralt or mfcalt: :mpltype:`color`
## markersize or ms: float
## markevery: None or int or (int, int) or slice or list[int] or float or (float, float) or list[bool]
## mouseover: bool
## path_effects: list of `.AbstractPathEffect`
## picker: float or callable[[Artist, Event], tuple[bool, dict]]
## pickradius: float
## rasterized: bool
## sketch_params: (scale: float, length: float, randomness: float)
## snap: bool or None
## solid_capstyle: `.CapStyle` or {'butt', 'projecting', 'round'}
## solid_joinstyle: `.JoinStyle` or {'miter', 'round', 'bevel'}
## transform: `~matplotlib.transforms.Transform`
## url: str
## visible: bool
## xdata: 1D array
## ydata: 1D array
## zorder: float

La consola de scripts de Spyder permite crear “celdas” a semejanza de las celdas de los notebooks. Se separa el código mediante # %%. Debe haber un cierre de celda (# %%) para que funcione como tal.
El siguiente paso es personalizar las etiquetas de los ejes, el título del gráfico y la ubicación de los tick marks:
#%%
_ = plt.plot(x, y, 'r-', marker = 'd')
_ = plt.xlabel('Año')
_ = plt.ylabel('Población (millones)')
_ = plt.title('Evolución en Uganda')
_ = plt.yticks([45, 47, 49])
_ = plt.xticks([2016, 2021])
Para controlar los límites se utiliza plt.axis que controla [xmin, xmax, ymin, ymax]
#%%
_ = plt.plot(x, y, 'r--', marker = 'o')
_ = plt.xlabel('Año')
_ = plt.ylabel('Población (millones)')
# plt.title('Evolución en Uganda')
_ = plt.axis([2016, 2021, 40, 50])
Probemos a superponer un segundo gráfico:
#%%
z = [40,42,44,46,48,50]
_ = plt.plot(x,y, marker='d', linestyle = '-', color = 'r')
_ = plt.plot(x,z, marker='o', linestyle = '-', color = 'g')
_ = plt.xlabel('Año')
_ = plt.ylabel('Población (millones)')
_ = plt.title('Evolución en Uganda e Indonesia')
_ = plt.yticks([41,43,45, 47, 49])
Para ejecutar una celda completa utilice el atajo: [Crtl]+[Enter]
Ahora una leyenda para diferenciar las series:
# Leyenda
z = [40,42,44,46,48,50]
_ = plt.plot(x,y, marker='d', linestyle = '--', color = 'r',
label = 'Uganda')
_ = plt.plot(x,z, marker='o', linestyle = '-', color = 'g',
label = 'Indonesia')
_ = plt.xlabel('Año')
_ = plt.ylabel('Población (millones)')
_ = plt.title('Evolución')
_ = plt.ylim([40, 50])
_ = plt.yticks([41,43,45, 47, 49])
_ = plt.legend(loc='lower right')
¿Cómo salvar el resultado gráfico?
#%%
_ = plt.plot(x, y, marker = 'd', linestyle = '--', color = 'r',
label = 'País')
plt.savefig('./Imagenes y videos/graficaGuardada.jpg')
Se puede especificar en pulgadas el tamaño de la figura.
_ = plt.figure(figsize=(5,3))
_ = plt.plot(x, y, marker = 'd', linestyle = '--', color = 'r',
label = 'País')
Los ejemplos vistos son gráficos de dispersión o scatter plots.
Ahora observemos un gráfico de barras:

La función plt.clf() limpia el buffer del plt para que no conserve definiciones de figuras anteriores.
La función plt.cla() limpia el buffer del “eje” para que no conserve definiciones de figuras anteriores.

El histograma
plt.clf()
edades = [45,53,42,45,63,52,42,39,32,45,46,45,48,52,18,32,23,56,89,48]
bins = [0,40,55,100]
_ = plt.hist(edades, bins, edgecolor='black')
Observe que se especificó el límite de cada bin. Lo usual es dejar que el módulo plt los calcule automáticamente:

Diagrama de caja y bigotes

El diagrama de dispersión ó scatter plot de manera explícita:
plt.clf()
x = [45,53,42,45,63,52,42,39,32,45,46,45,48,52,18,32,23,56,89,48]
y = [53,42,45,63,52,42,39,32,45,46,45,48,52,18,32,23,56,89,48,23]
_ = plt.scatter(x,y)
Colores
Para observar la lista de colores.
Se puede especificar el color de diversas maneras:
Mediante la paleta RGB (red, green, blue):
x = [45,53,42,45,63,52,42,39,32,45,46,45,48,52,18,32,23,56,89,48]
y = [53,42,45,63,52,42,39,32,45,46,45,48,52,18,32,23,56,89,48,23]
_ = plt.scatter(x, y, color= np.array([150,250,56])/255)
Mediante numeración hexadecimal (no importa si se usan mayúsculas o minúsculas)

Mediante el nombre del color:

Si se desea realizar el gráfico en escala de grises, se puede colocar entre comillas un número entre cero y uno, cero indicando negro y uno indicando blanco.

Para un gráfico sencillo, se coloca entre comillas la inicial de uno de los ocho colores de la paleta básica de matplotlib:
‘b’ de blue
‘g’ de green
‘r’ de red
‘c’ de cyan
‘m’ de magenta
‘y’ de yellow
‘k’ de black
‘w’ de white
Para la mayoría de las opciones funciona el parámetro alpha que hace referencia al nivel de opacidad. Por ejemplo, un 20% de opacidad significa transparentoso:

Para acceder a las paletas preestablecidas se utiliza el comando get_cmap.
Para el siguiente ejemplo se cargará una paleta para datos cualitativos:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# Seleccione n colores
n = 7
# Cargue la lista de paletas
from_list = matplotlib.colors.LinearSegmentedColormap.from_list
# Asigne una paleta, y los n colores de ésta
cm = from_list(None, plt.cm.Set1(range(0, n)), n)
# Asigne los ejes x, y, y los colores.
x = np.arange(99)
y = x//11 + x%11
colores = x % n
_ = plt.scatter(x, y, c = colores, cmap=cm)
# plt.clim(-0.5, n-0.5)
barraColores = plt.colorbar(ticks = range(0, n), label = 'Grupo')
# barraColores.ax.tick_params(length=2)
El nombre de cmap o “color map” proviene de las matemáticas, donde mapear se refiere a “una operación que asocia cada elemento de un conjunto dado con uno o más elementos de un segundo conjunto”. En este caso, se asocian valores con colores.
Es posible aplicarle estilos preestablecidos:
plt.style.use(['dark_background'])
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(6,3))
x = [45,53,42,45,63,52,42,39,32,45,46,45,48,52,18,32,23,56,89,48]
y = [53,42,45,63,52,42,39,32,45,46,45,48,52,18,32,23,56,89,48,23]
_ = plt.scatter(x, y, color= np.array([150,250,56])/255)
_ = plt.title('Titulo de la gráfica de dispersión')
_ = plt.ylabel('Valores en eje Y')
plt.xlabel('valores en eje X')
# plt.show()He aqui un ejemplo con un colormap continuo:
plt.style.use(['ggplot'])
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.colors as clr
import numpy as np
matriz = np.random.rand(10,10)
colormap = clr.LinearSegmentedColormap.from_list('azul personalizado', ['#2441FF','#DCE6FF'], N=256)
imagen= plt.matshow(matriz, cmap=colormap)
plt.colorbar(imagen)
# plt.show()
Los \(256\) colores entre un valor y el otro son finitos, pero para la capacidad humana se ven como un degrade continuo, de valores infinitos. LinearSegmentedColormap es el responsable de interpolar los \(254\) tonos intermedios, a distancia uniformes. De ahí viene el nombre de lineal. cmapasocia los valores continuos entre cero u uno de la matriz con los \(256\) tonos, con el objeto de representar con un tono diferente el valor de cada celda de la matriz.
La visualización presentada para el ejemplo se denomina, mapa de calor (heatmap en inglés). Se regresará a ésta más adelante.
Diagrama para valores discretos
Se ha presentado el diagrama de barras para conteo de valores categóricos y el histograma para valores numéricos continuos. Los valores discretos se visualizan preferentemente con “lolly-pops”. Colombinas o bom-bom-bum en español. Con ese objeto se utiliza la función stem() de matplotlib.
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(4,3))
x = np.arange(4, 21, 0.5)
y = x**2
fig, ax = plt.subplots()
ax.stem(x, y, bottom = 0, linefmt = 'm', markerfmt = 'om', basefmt = 'm')
# plt.show()
Los formatos de la línea (linefmt y basefmt) aceptan los mismos parámetros que el tercer argumento de las visualizaciones de líneas, es decir, color, trazado y grosor de línea.
El formato del marcador (markerfmt) acepta los mismos parámetros que los marcadores, es decir, forma, tamaño y color del borde y del relleno. Es válido dejar sólo las líneas y prescindir del marcador especificando markerfmt=” “.
No aceptan la personalización de color. Bueno, aceptan un color en formato hexadecimal, pero entonces no es posible modificar las otras propiedades, trazado o forma, de las líneas y el marcador respectivamente.
La función stem acepta también la pareja (parámetro = argumento): orientation = “horizontal”.
import matplotlib.pyplot as plt
import numpy as np
_ = plt.figure(figsize=(1, 0.6))
x = np.arange(4, 21, 0.5)
y = x**2 - 200
fig, ax = plt.subplots()
_ = ax.stem(x, y, bottom = -200, linefmt = 'm-.', markerfmt = ' ', basefmt = 'k')
El parámetro bottom indica la altura en el eje y de la que parte la línea horizontal de base.
Con stem() no se puede prescindir de las líneas y dejar sólo la marca, porque se trata entonces de un scatter().