Matplotlib no es solo para gráficos estáticos. Si bien las GUI generalmente se crean con bibliotecas y marcos de GUI como PyQt, Tkinter, Kivy y wxPython, y aunque Python tiene una excelente integración con PyQt, Tkinter y wxPython: no hay necesidad de usar ninguno de estos para algunas funciones básicas de GUI, a través de Widgets de Matplotlib.
El matplotlib.widgets
módulo tiene varias clases, incluyendo el AxesWidget
, de los cuales Button
s, CheckButton
s, Slider
s, TextBox
es, etc se derivan. Todos estos aceptan la Axes
se agregan como el único argumento de constructor obligatorio, y su posicionamiento debe configurarse manualmente. Una cosa a tener en cuenta es que el widget es los ejes, por lo que creará un Axes
instancia para cada widget.
Otra cosa a tener en cuenta es que tienes que mantener las referencias a los widgets de lo contrario, podrían recolectar basura.
Cada uno de ellos también se puede desactivar configurando active
a False
, en cuyo caso, no responderán a ningún evento, como hacer clic en ellos. Dicho esto, podemos introducir un nuevo tipo de interactividad en nuestras tramas, a través de varios elementos y componentes de la GUI.
Nota: Matplotlib no está destinado a ser utilizado para la creación de GUI de alta calidad, ni para sistemas fáciles de usar. Estos widgets son rudimentarios, no se ven muy bien y tienen una funcionalidad limitada. Están pensados como una forma de crear prototipos y probar cosas, en lugar de enviarlos realmente.
Si ha trabajado con PyQt anteriormente, puede notar que la sintaxis general y el enfoque para agregar estos widgets, así como para conectarlos a los controladores de eventos, es bastante familiar.
Agregar botones
Comencemos con botones - La matplotlib.widgets
módulo define un Button
clase. Para conectarnos a él, llamamos al on_clicked()
función, que ejecuta la función que proporcionamos. Una vez que se ha detectado un clic, la función se ejecuta.
Mientras creamos el botón, le asignamos un Axes
a él, utilizado para el posicionamiento. También podemos pasar en un label
en ese momento, para agregar texto y anotarlo para un usuario. los color
y hovercolor
Los argumentos definen el color del botón antes y después de pasar el cursor sobre él.
Ya que nos ocupamos del posicionamiento y el espacio para todos los widgets, creemos un Figure
y Axes
, deje algo de espacio en la parte inferior para agregar un botón y trace un gráfico de dispersión vacío. Luego, definiremos un EventHandler
clase, que tiene un solo método add_random()
. El método genera dos números aleatorios y traza un marcador para ellos en el Axes
hemos creado antes y llama plt.draw()
, que vuelve a dibujar el Figure
. A la hora de actualizar parcelas, siempre tendremos que llamar plt.draw()
de nuevo para actualizarlo:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2)
plot = ax.scatter([], []) class EventHandler: def add_random(self, event): x = np.random.randint(0, 100) y = np.random.randint(0, 100) ax.scatter(x, y) plt.draw() # Axes for the Button and positioning
# xposition and yposition in percentages, width, height
button_ax = plt.axes([0.7, 0.05, 0.2, 0.07])
# Create Button and assign it to `button_ax` with label
button = Button(button_ax, 'Add Random', color='green', hovercolor='red')
# On a detected click, execute add_random()
button.on_clicked(EventHandler().add_random) plt.show()
Esto da como resultado una Figure
, con un vacío Axes
dentro de él y un botón en la esquina superior derecha de la pantalla, en su propio Axes
:
Y después de presionar el botón un par de docenas de veces, nuestro ax
se completará con marcadores aleatorios:
En términos más prácticos, podríamos crear un Cycle de funciones que se trazarán con cada pulsación de botón. Esto requiere algunos ajustes en el EventHandler
, así como otro botón para volver a recorrer ese ciclo.
Usemos el Calidad del vino tinto conjunto de datos de nuevo, y visualizar varias características contra el Alcohol rasgo. Ya que no podemos molestarnos en graficar estos individualmente escribiendo el código para graficar una característica contra la otra, y luego modificando ese código para graficar otra característica contra la otra.
La creación de una matriz de dispersión podría ayudarnos aquí, pero si el conjunto de datos tiene muchas características, será bastante ilegible y no llegaremos muy lejos. si te gustaria tener ambas parcelas a gran escala que puede ver e interpretar fácilmente, así como como tener varias funciones ciclándose sin ningún esfuerzo adicional; puede automatizar este proceso con botones:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import Button fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2) df = pd.read_csv('winequality-red.csv')
plot = ax.scatter([], []) class EventHandler: i = 0 # Find and plot next feature, re-draw the Axes def next_feature(self, event): # If the counter is at the end of the columns # Revert it back to 0 to cycle through again if self.i >= len(df.columns): self.i = 0 # Clear Axes from last plot ax.cla() # Plot a feature against a feature located on the `i` column ax.scatter(df['alcohol'], df.iloc[:,self.i]) # Set labels ax.set_xlabel('Alcohol') ax.set_ylabel(df.columns[self.i]) # Increment i self.i += 1 # Update Figure plt.draw() def previous_feature(self, event): # If the counter is at the start of the columns # Revert it back to the last column to cycle through if self.i <= 0: self.i = len(df.columns)-1 ax.cla() ax.scatter(df['alcohol'], df.iloc[:,self.i]) ax.set_xlabel('Alcohol') ax.set_ylabel(df.columns[self.i]) self.i -= 1 plt.draw() # Add buttons
button1_ax = plt.axes([0.7, 0.02, 0.2, 0.07])
next_button = Button(button1_ax, 'Next Feature')
next_button.on_clicked(EventHandler().next_feature) button2_ax = plt.axes([0.45, 0.02, 0.2, 0.07])
previous_button = Button(button2_ax, 'Previous Feature')
previous_button.on_clicked(EventHandler().previous_feature) plt.show()
El EventHandler
la clase ahora tiene dos métodos: next_feature()
y previous_feature()
. Ambos comprueban si el contador i
ha llegado al final o al principio de la lista de columnas, y para evitar una IndexError
, restablecemos el índice al valor opuesto y simulamos un Cycle. Yendo abajo 0
nos llevará de vuelta a la final de la lista de columnas, y pasar por encima de la última columna nos revertirá a la primera.
Después de determinar dónde estamos ubicados, nos Limpiar el Axes
, ya que estaríamos trazando de nuevo sobre una trama existente sin borrarla a través de cla()
(cloído axes). Alternativamente, también podría acumular relaciones de características, trazando una encima de la otra y usando el cla()
declaración al restablecer el índice al final/inicio del ciclo.
Después de borrar el Axes
– tenemos un lienzo despejado para pintar con el ax.scatter()
función. En este ejemplo, la función fija es Alcohol, por lo que está presente en todo momento. La otra función varía y se puede acceder a través de iloc[]
, pasando el índice de la columna. Esto devuelve un Series
que podemos usar en este gráfico. Del mismo modo, podemos acceder nombres de columna a través de su índice también – df.columns[index]
, que se utiliza para establecer la etiqueta del eje Y.
Finalmente, aumentamos/disminuimos el contador y llamamos plt.draw()
para actualizar el Figure
:
Una vez que hacemos clic en el Característica siguiente botón, la siguiente característica en la lista de columnas se trazará contra Alcohol, y la Figure
se actualizará adecuadamente: las etiquetas, los marcadores y la escala. Lo mismo ocurre al revés - Característica anterior recorrerá la lista en sentido contrario, permitiéndonos ir y venir, con un mecanismo de seguridad que pone a cero nuestro contador cada vez que llegamos al final o al principio del ciclo.
Adición de botones de opción y casillas de verificación
Botones de radio se utilizan para permitir que un usuario seleccione un valor de varios valores. Solo se puede seleccionar un botón de radio a la vez y, por lo general, representan una opción. Casillas de verificación se puede usar si desea permitir que el usuario seleccione varias opciones a la vez.
Nota: Existe una capacidad muy limitada para verificar si una casilla de verificación está on or off. De hecho, no hay ninguno fuera de la caja. Solo puede verificar si la casilla está planchado or no, lo que plantea una seria limitación a la forma en que se puede utilizar, ya que no tenemos idea de en qué estado estaba antes de eso. La única alternativa es mantener su propio contador/comprobación del estado actual del cuadro con un valor booleano y modificar la lógica en función de eso.
Esto le permitiría, por ejemplo, agregar una casilla de verificación para cada argumento de personalización de una determinada trama, lo que permite al usuario configurarlos True
or False
(marcado o no marcado), o cualquier otro mapeo no conflictivo basado en estos estados.
Sin embargo, dado que la API es limitada en sí misma, también nos limitaremos al uso previsto: encender y apagar cosas. Tendremos dos características, que podemos convertir on y off a través de una casilla de verificación. Tenga en cuenta que incluso esta funcionalidad está limitada a objetos para los que puede verificar si están visibles o no.
Por otro lado, no queremos permitir que el usuario aplique dos escalas a la vez, o que establezca dos límites X a la vez, ya que solo se aplicaría la declaración llamada segundo en la secuencia. Para estos, usaríamos botones de radio.
Agreguemos un par de botones de radio para permitir que el usuario seleccione el rango del eje a través de un par de botones de radio, pero también permitirles activar visualizaciones de funciones on y off:
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import CheckButtons
from matplotlib.widgets import RadioButtons fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2) df = pd.read_csv('winequality-red.csv') # Plot two line plots for two features, and turn them invisible
line1, = ax.plot(df['fixed acidity'], visible=False)
line2, = ax.plot(df['citric acid'], visible=False) class EventHandler: # set_range handler def set_range(label): if (label == 'Small Range'): ax.set_xlim(0, 1600) ax.set_ylim(0, 25) else: ax.set_xlim(0, 1600) ax.set_ylim(0, 50) plt.draw() # Turn off, if on, and on if off def apply_features(label): if (label == 'Fixed Acidity'): line1.set_visible(not line1.get_visible()) elif (label == 'Citric Acid'): line2.set_visible(not line2.get_visible()) plt.draw() # Add radio buttons and checkboxes
ranges_ax = plt.axes([0.7, 0.02, 0.2, 0.1])
range_radio_buttons = RadioButtons(ranges_ax, ('Small Range', 'Large Range'))
range_radio_buttons.on_clicked(EventHandler.set_range) checkboxes_ax = plt.axes([0.4, 0.02, 0.25, 0.1])
checkboxes = CheckButtons(checkboxes_ax, ('Fixed Acidity', 'Citric Acid'))
checkboxes.on_clicked(EventHandler.apply_features) plt.show()
Una vez más, tenemos dos métodos en el EventHandler()
clase - set_range()
y apply_features()
. set_range()
establece el rango en "pequeño" o "grande", ajustando el Axes
' Límites X e Y. los apply_features()
función altera la visible
campo de los gráficos de líneas que hicimos anteriormente, en función de su actual visible
estado. Si visible == True
, desactivamos Line Plot y viceversa.
Tenemos que confiar en la capacidad incorporada para verificar la visibilidad de los diagramas de líneas, ya que no podemos verificar si la casilla de verificación se marcó o no antes. Esta misma habilidad se puede emular con un status
booleano en el ámbito de la EventHandler()
clase, que se establece en True
y False
en cada clic, para los tipos de gráficos que no admiten la verificación si están visibles de forma predeterminada.
Ejecutar este código da como resultado un Figure
con dos juegos de botones en la parte inferior. Si marcamos ambas casillas, aparecerán ambos Line Plots:
Podemos apagarlos individualmente:
Y podemos cambiar el rango de la Axes
a través de los botones de opción:
Agregar cuadros de texto
Cajas de texto se utilizan para recoger datos del usuario, y podemos modificar los gráficos en función de estos datos. Por ejemplo, podemos pedirle a un usuario que ingrese el nombre de una característica, o que inserte una función para que nuestra gráfica la visualice. Por supuesto, trabajar con la entrada del usuario puede ser complicado: siempre hay casos extremos a los que prestar atención.
Escribamos un script que permita al usuario ingresar un nombre de la característica de un conjunto de datos, y el Axes
actualizaciones en cada presentación para reflejar la entrada. Para la comodidad del usuario, le informaremos si la entrada no pudo coincidir con un nombre de columna:
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import TextBox fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2) df = pd.read_csv('winequality-red.csv') class EventHandler: def submit(feature_name): if feature_name != "" or feature_name != None: if feature_name in df: ax.cla() ax.plot(df[feature_name]) else: if len(textbox_ax.texts) > 2: del textbox_ax.texts[-1] textbox_ax.text(-2, 0.4, feature_name + ' was not found.') plt.draw() textbox_ax = plt.axes([0.7, 0.02, 0.2, 0.1])
textbox = TextBox(textbox_ax, 'Feature Name')
textbox.on_submit(EventHandler.submit) plt.show()
Tenemos un control simple para ver si el proporcionado feature_name
está en blanco o None
, en cuyo caso, no hacemos nada. Si no, verificamos si el feature_name
está presente en el DataFrame
, adjuntando un mensaje de que no se encontró la característica si no está presente. Sin embargo, antes de adjuntar el texto, debemos asegurarnos de que se elimine el mensaje anterior, para que el nuevo no se superponga con él. los axes.texts
propiedad es una lista de todos los Text
instancias en un Axes
. Desde el Axes
ya tiene un Text
ejemplo, perteneciente a nuestro TextBox
, no queremos eliminar nada si hay 2 o menos Text
instancias presentes: el mensaje de error y el TextBox
etiqueta.
Si está por encima de dos, ya tenemos un mensaje de error, que debe eliminarse.
Si la característica is Presente en el DataFrame
, sin embargo, borramos el Axes
y trazarlo:
Adición de selectores de intervalo
Selectores de rango se puede utilizar para permitir al usuario seleccionar un intervalo de datos y centrarse en él, estableciendo los límites del eje en función de esa selección. De forma predeterminada, muchas bibliotecas admiten esta funcionalidad, aunque desafortunadamente Matplotlib no lo hace y tendremos que hacerlo manualmente. Además, tendremos que añadir un extra "Reiniciar" botón si queremos alejar .
Para agregar un Selector de tramo, no necesitamos dedicar un nuevo Axes
para él, podemos adjuntarlo a uno existente, lo que tiene mucho sentido. Al generar un SpanSelector
, suministramos el Axes
al que pertenece, así como el controlador de eventos, seguido de 'horizontal'
or 'vertical'
, que gira la Axes
y Selector de rango ambos.
El useblit
el argumento generalmente se establece en True
porque mejora el rendimiento en la mayoría de los backends. Además, hemos agregado algunas propiedades de estilo, como configurar el alpha
del rectángulo creado como Selector de extensión para 0.5
y del facecolor
a un agradable tab:blue
:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import SpanSelector
from matplotlib.widgets import Button fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2) df = pd.read_csv('AmesHousing.csv') ax.scatter(x = df['Year Built'], y = df['Total Bsmt SF'], alpha = 0.6) class EventHandler: def select_horizontal(x, y): ax.set_xlim(x, y) plt.draw() def reset(self): ax.set_xlim(df['Year Built'].min(), df['Year Built'].max()) plt.draw span_horizontal = SpanSelector(ax, EventHandler.select_horizontal, 'horizontal', useblit=True, rectprops=dict(alpha=0.5, facecolor='tab:blue')) button_ax = plt.axes([0.7, 0.02, 0.2, 0.07])
button = Button(button_ax, 'Reset')
button.on_clicked(EventHandler.reset) plt.show()
Ejecutar esto genera un gráfico en el que podemos seleccionar tramos y acercarlos configurando los límites de los ejes en los valores proporcionados:
Adición de controles deslizantes
Controles deslizantes permita a los usuarios seleccionar entre muchos valores de forma intuitiva deslizando un marcador y seleccionando un valor. Por lo general, los controles deslizantes se utilizan para actualizar continuamente algún valor en un gráfico, como su rango or incluso una característica. Por ejemplo, puede ajustar el valor de una constante a través de un control deslizante, que a su vez afecta una función que se basa en esa constante.
Escribamos un script que nos permita cambiar los límites de los ejes Y y X, a través de un control deslizante, que nos permitirá cambiar la perspectiva desde la que estamos viendo nuestros datos:
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2, left=0.2) df = pd.read_csv('winequality-red.csv')
plot, = ax.plot(df['volatile acidity']) class EventHandler: def update(val): ax.set_ylim(0, yslider.val) ax.set_xlim(0, xslider.val) plt.draw() xslider_ax = plt.axes([0.35, 0.03, 0.5, 0.07])
xslider = Slider( ax=xslider_ax, label="X-limit", valmin=0, valmax=len(df['volatile acidity']), valinit=len(df['volatile acidity']), orientation="horizontal"
) yslider_ax = plt.axes([0.03, 0.2, 0.07, 0.5])
yslider = Slider( ax=yslider_ax, label="Y-limit", valmin=0, valmax=3, valinit=1.5, orientation="vertical"
) xslider.on_changed(EventHandler.update)
yslider.on_changed(EventHandler.update) plt.show()
Hemos ajustado el relleno para permitir un control deslizante a la izquierda y en la parte inferior de la Axes
, y trazó un diagrama de líneas simple. Agregar un control deslizante requiere que hagamos un Axes
para él, como con la mayoría de los otros widgets, y asígnelo al ax
argumento de la Slider
a través del constructor. Además, podemos establecer los valores mínimo, máximo e inicial del control deslizante. Por lo general, serán rangos dinámicos, según los datos que esté trazando, pero también se pueden establecer manualmente valores escalares.
Finalmente, Slider
Los s se pueden orientar horizontal o verticalmente. Dado que están destinados a actualizarse continuamente con solo deslizar el mouse, el on_changed()
La función se utiliza para desencadenar una respuesta cuando un usuario proporciona una entrada. Hemos ajustado el EventHandler
clase con un update()
función que simplemente ajusta los valores de los límites X e Y en función de la val
ue de los respectivos controles deslizantes.
Ejecutar este código producirá un gráfico con dos controles deslizantes, que podemos usar para cambiar el alcance de la Axes
:
- de la máquina
- Todos
- Permitir
- ya haya utilizado
- Otra
- abejas
- enfoque
- argumentos
- en torno a
- Comienzo
- "Ser"
- Box
- incorporado
- llamar al
- servicios sociales
- cases
- el cambio
- comprobación
- código
- Columna
- podría
- Parejas
- Creamos
- Current
- Estado actual
- datos
- dedicado
- detectado
- docena
- lugar de trabajo dinámico
- pasan fácilmente
- Southern Implants
- Evento
- Eventos
- ejemplo
- excelente,
- Feature
- Caracteristicas
- Nombre
- Focus
- encontrado
- función
- a la fatiga
- General
- va
- maravillosa
- Verde
- es
- ayuda
- esta página
- Cómo
- HTTPS
- idea
- Incluye
- índice
- integración
- IT
- Etiquetas
- large
- Limitada
- línea
- Lista
- Matrix
- MEJOR DE TU
- números
- Opciones
- Otro
- de otra manera
- actuación
- la perspectiva
- presente
- prensa
- producir
- perfecta
- Radio
- distancia
- RE
- respuesta
- Resultados
- devoluciones
- Safety
- Said
- Escala
- Pantalla
- seleccionado
- sentido
- set
- pólipo
- sencillos
- chica
- So
- Espacio
- comienzo
- Estado
- Posicionamiento
- Zonas
- Estado
- suministro
- SOPORTE
- Todas las funciones a su disposición
- test
- A través de esta formación, el personal docente y administrativo de escuelas y universidades estará preparado para manejar los recursos disponibles que derivan de la diversidad cultural de sus estudiantes. Además, un mejor y mayor entendimiento sobre estas diferencias y similitudes culturales permitirá alcanzar los objetivos de inclusión previstos.
- equipo
- parte superior
- Actualizar
- Actualizaciones
- us
- usuarios
- propuesta de
- Ver
- la visibilidad
- visibles
- sean
- sin
- trabajado
- trabajando
- la escritura
- X
- año
- Zoom