Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Widgets Matplotlib

Matplotlib n'est pas uniquement destiné aux tracés statiques. Alors que les interfaces graphiques sont généralement créées avec des bibliothèques et des frameworks d'interface graphique tels que PyQtName, Tkinter, Kivy ainsi que wxPython, et bien que Python ait une excellente intégration avec PyQt, Tkinter ainsi que wxPython – il n'est pas nécessaire d'utiliser aucun de ces éléments pour certaines fonctionnalités de base de l'interface graphique, via Widgets Matplotlib.

Les matplotlib.widgets Le module comporte plusieurs classes, dont la AxesWidget, parmi lesquels Buttons, CheckButtons, Sliders, TextBoxes, etc. sont dérivés. Tous acceptent le Axes ils sont ajoutés comme seul et unique argument de constructeur obligatoire, et leur positionnement doit être défini manuellement. Une chose à noter est que le le widget est les axes, vous allez donc créer un Axes instance pour chaque widget.

Une autre chose à noter est que il faut garder les références aux widgets sinon, ils pourraient faire ramasser les ordures.

Chacun d'eux peut également être désactivé en définissant active à False, auquel cas ils ne répondront à aucun événement, comme un clic dessus. Cela étant dit, nous pouvons introduire un nouveau type d’interactivité dans nos tracés, à travers divers éléments et composants de l’interface graphique.

Remarque: Matplotlib n'est pas destiné à être utilisé pour la création d'interfaces graphiques de haute qualité, ni pour des systèmes conviviaux. Ces widgets sont rudimentaires, n'ont pas vraiment fière allure et ont des fonctionnalités limitées. Ils sont destinés à créer des prototypes et à tester des choses, plutôt que de les expédier réellement.

Si vous avez déjà travaillé avec PyQt, vous remarquerez peut-être que la syntaxe générale et l'approche pour ajouter ces widgets, ainsi que pour les connecter aux gestionnaires d'événements, sont assez familières.

Ajout de boutons

Commençons par boutons - L' matplotlib.widgets le module définit un Button classe. Pour s'y connecter, on appelle le on_clicked() fonction, qui exécute la fonction que nous fournissons. Une fois qu'un clic a été détecté, la fonction s'exécute.

Lors de la création du bouton, nous attribuons un Axes à lui, utilisé pour le positionnement. On peut aussi passer dans un label à ce moment-là, pour ajouter du texte et l'annoter pour un utilisateur. Le color ainsi que hovercolor les arguments définissent la couleur du bouton avant et après son survol.

Puisque nous nous occupons du positionnement et de l'espace pour tous les widgets, créons un Figure ainsi que Axes, prévoyez un certain espacement en bas pour ajouter un bouton et tracez un nuage de points vide. Ensuite, nous définirons un EventHandler classe, qui a une seule méthode add_random(). La méthode génère deux nombres aléatoires et trace un marqueur pour eux sur le Axes nous avons déjà créé et appelle plt.draw(), qui redessine le Figure. Lors de la mise à jour des parcelles, nous devrons toujours appeler plt.draw() encore une fois pour le mettre à jour :

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()

Cela se traduit par un Figure, avec un vide Axes à l'intérieur et un bouton dans le coin supérieur droit de l'écran, à part entière Axes:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Et après avoir appuyé sur le bouton plusieurs dizaines de fois, notre ax sera rempli de marqueurs aléatoires :

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

En termes plus pratiques, nous pourrions créer un cycle de fonctionnalités à tracer à chaque pression sur un bouton. Cela nécessite quelques ajustements au EventHandler, ainsi qu'un autre bouton pour revenir dans ce cycle.

Utilisons le Qualité du vin rouge à nouveau l'ensemble de données et visualisez plusieurs caractéristiques par rapport à l'ensemble de données Alcool fonctionnalité. Puisque nous ne pouvons pas prendre la peine de les tracer individuellement en écrivant le code pour tracer une fonctionnalité par rapport à l'autre, puis en modifiant ce code pour tracer une autre fonctionnalité par rapport à l'autre.

Créer une matrice de dispersion pourrait nous aider ici, mais si l'ensemble de données comporte de nombreuses fonctionnalités, il sera assez illisible et nous n'irons pas loin. Si vous souhaitez avoir tous les deux des tracés à grande échelle que vous pouvez facilement visualiser et interpréter, ainsi que comme avoir plusieurs fonctionnalités à parcourir sans aucun effort supplémentaire – vous pouvez automatiser ce processus avec des boutons :

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()

Les EventHandler la classe a maintenant deux méthodes – next_feature() ainsi que previous_feature(). Ces deux éléments vérifient si le compteur i a atteint la fin ou le début de la liste des colonnes – et pour éviter un IndexError, nous réinitialisons l'index à la valeur opposée et simulons un cycle. Descendre en dessous 0 nous ramènera au fin de la liste des colonnes, et passer au-dessus de la dernière colonne nous ramènera à la première.

Après avoir vérifié où nous nous trouvons – nous Effacer le Axes, puisque nous tracerions à nouveau au-dessus d'un tracé existant sans l'effacer via cla() (cloreille axes). Vous pouvez également empiler les relations entre les fonctionnalités, en les traçant les unes sur les autres et en utilisant le cla() lors de la réinitialisation de l'index à la fin/au début du cycle.

Après avoir effacé le Axes – nous avons une toile dégagée sur laquelle peindre avec le ax.scatter() fonction. Dans cet exemple, la fonctionnalité fixe est Alcool, donc il est présent à tout moment. L'autre fonctionnalité varie et est accessible via iloc[], en passant l'index de la colonne. Cela renvoie un Series que nous pouvons utiliser dans cette intrigue. De même, nous pouvons accéder noms de colonnes via leur index également – df.columns[index], qui est utilisé pour définir l’étiquette de l’axe Y.

Enfin, on augmente/diminue le compteur et on appelle plt.draw() pour mettre à jour le Figure:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Une fois que nous cliquons sur le Fonctionnalité suivante bouton, l'entité suivante dans la liste des colonnes sera tracée par rapport à Alcool, et le Figure seront mis à jour de manière appropriée – les étiquettes, les marqueurs et l’échelle. La même chose se passe dans l’autre sens – Fonctionnalité précédente parcourra la liste dans le sens opposé, nous permettant de faire des allers-retours, avec un mécanisme de sécurité qui réinitialise notre compteur à chaque fois que nous arrivons à la fin ou au début du cycle.

Ajout de boutons radio et de cases à cocher

Boutons radio sont utilisés pour permettre à un utilisateur de sélectionner une valeur sur plusieurs valeurs. Un seul bouton radio peut être sélectionné à la fois et il représente généralement un choix. Cases à cocher peut être utilisé si vous souhaitez permettre à l'utilisateur de sélectionner plusieurs options à la fois.

Remarque: Il existe une capacité très limitée à vérifier si une case à cocher est on or de rabais. En fait, il n’y en a aucun de prêt à l’emploi. Vous ne pouvez vérifier que si la case est pressé or ne sauraient , ce qui pose une sérieuse limitation à la façon dont il peut être utilisé puisque nous n'avons aucune idée dans quel état il se trouvait avant cela. La seule alternative est de conserver votre propre compteur/vérification de l'état actuel de la boîte avec un booléen et de modifier la logique en fonction de cela.

Cela vous permettrait, par exemple, d'ajouter une case à cocher pour chaque argument de personnalisation d'une certaine parcelle, permettant à l'utilisateur de les définir True or False (coché ou décoché), ou tout autre mappage non conflictuel basé sur ces états.

Cependant, comme l'API elle-même est limitée, nous nous limiterons également à l'utilisation prévue : allumer et éteindre les choses. Nous aurons deux fonctionnalités que nous pouvons transformer on ainsi que de rabais via une case à cocher. Notez que même cette fonctionnalité est limitée aux objets pour lesquels vous pouvez vérifier s'ils sont visibles ou non.

D'un autre côté, nous ne voulons pas permettre à l'utilisateur d'appliquer deux échelles à la fois, ou de définir deux limites X à la fois, puisque seule l'instruction appelée deuxième dans la séquence serait appliquée. Pour ceux-ci, nous utiliserions des boutons radio.

Ajoutons quelques boutons radio pour permettre à l'utilisateur de sélectionner la plage des axes via quelques boutons radio, mais leur permettons également d'activer les visualisations des fonctionnalités. on ainsi que de rabais:

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()

Encore une fois, nous avons deux méthodes dans le EventHandler() classer - set_range() ainsi que apply_features()L’ set_range() La méthode définit la plage sur « petite » ou « grande », en ajustant la Axes' Limites X et Y. Le apply_features() la fonction modifie le visible champ des tracés linéaires que nous avons créés plus tôt, en fonction de leur visible statut. Si visible == True, nous désactivons le tracé linéaire, et vice versa.

Nous devons nous appuyer sur la capacité intégrée pour vérifier la visibilité des tracés linéaires, car nous ne pouvons pas vérifier si la case a été cochée ou non auparavant. Cette même capacité peut être imitée avec un status booléen dans le cadre de EventHandler() classe, qui est définie sur True ainsi que False à chaque clic, pour les types de tracés qui ne prennent pas en charge la vérification s'ils sont visibles dès le départ.

L'exécution de ce code entraîne un Figure avec deux jeux de boutons en bas. Si nous cochons les deux cases, les deux tracés linéaires apparaîtront :

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Nous pouvons les désactiver individuellement :

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Et nous pouvons changer la portée du Axes via les boutons radio :

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Ajout de zones de texte

Zones de texte être habitué recueillir données de l’utilisateur – et nous pouvons modifier les tracés en fonction de ces données. Par exemple, nous pouvons demander à un utilisateur de saisir le nom d’une fonctionnalité ou d’insérer une fonction que notre tracé pourra visualiser. Bien sûr, travailler avec les entrées des utilisateurs peut être délicat – il y a toujours des cas extrêmes à surveiller.

Écrivons un script qui permet à l'utilisateur de saisir un nom de la fonction d'un ensemble de données, et le Axes des mises à jour sur chaque soumission pour refléter les commentaires. Pour la commodité de l'utilisateur, nous lui ferons savoir si l'entrée ne peut pas correspondre à un nom de colonne :

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()

Nous avons un simple contrôle pour voir si le feature_name est vide ou None, auquel cas nous ne faisons rien. Dans le cas contraire, nous vérifions si le feature_name est présent dans le DataFrame, en joignant un message indiquant que la fonctionnalité n'a pas été trouvée si elle n'est pas présente. Cependant, avant de joindre le texte, nous devons nous assurer que le message précédent est supprimé, afin que le nouveau ne le chevauche pas. Le axes.texts la propriété est une liste de tous les Text instances sur un Axes. Depuis le Axes a déjà un Text par exemple, appartenant à notre TextBox, nous ne voulons rien supprimer s'il y en a 2 ou moins Text instances présentes – le message d’erreur et le TextBox étiquette.

Si la valeur est supérieure à deux, nous avons déjà un message d'erreur qui doit être supprimé.

Si la fonctionnalité is Présent dans le DataFrame, cependant, nous effaçons le Axes et tracez-le :

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Ajout de sélecteurs de durée

Sélecteurs de portée peut être utilisé pour permettre à l'utilisateur de sélectionner une étendue de données et de se concentrer dessus, en définissant les limites de l'axe en fonction de cette sélection. Par défaut, de nombreuses bibliothèques prennent en charge cette fonctionnalité, mais malheureusement, Matplotlib ne le fait pas et nous devrons le faire manuellement. De plus, nous devrons ajouter un supplément "Réinitialiser" bouton si nous voulons Effectuer un zoom arrière également.

Ajouter un Sélecteur de portée, nous n'avons pas besoin de consacrer un tout nouveau Axes pour cela – nous pouvons le rattacher à un existant, ce qui a beaucoup de sens. Lors de la génération d'un SpanSelector, nous fournissons le Axes auquel il appartient, ainsi que le gestionnaire d'événements, suivi de 'horizontal' or 'vertical', qui fait tourner le Axes ainsi que Sélecteur de portée les deux.

Les useblit l'argument est généralement défini sur True car il améliore les performances sur la plupart des backends. De plus, nous avons ajouté quelques propriétés de style, telles que la définition du alpha du rectangle créé en tant que sélecteur d'étendue pour 0.5 et par facecolor à un gentil 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()

L'exécution de ceci génère un tracé sur lequel nous pouvons sélectionner des étendues et zoomer dessus en définissant les limites des axes sur les valeurs fournies :

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Ajout de curseurs

Sliders permettre aux utilisateurs de choisir intuitivement entre de nombreuses valeurs en faisant glisser un marqueur et en sélectionnant une valeur. En règle générale, les curseurs sont utilisés pour mettre à jour en permanence certaines valeurs d'un tracé, telles que sa plage. or même une fonctionnalité. Par exemple, vous pouvez ajuster la valeur d'une constante via un curseur, ce qui affecte à son tour une fonction qui repose sur cette constante.

Écrivons un script qui nous permet de modifier les limites des axes Y et X, via un curseur, ce qui nous permettra de changer la perspective dans laquelle nous visualisons nos données :

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()

Nous avons ajusté le rembourrage pour permettre l'insertion d'un curseur à gauche et en bas de l'écran. Axes, et tracé un simple tracé linéaire. L'ajout d'un curseur nous oblige à faire un Axes pour cela, comme avec la plupart des autres widgets, et attribuez-le au ax argument de la Slider via le constructeur. De plus, nous pouvons définir les valeurs minimales, maximales et initiales du curseur. Il s'agira généralement de plages dynamiques, basées sur les données que vous tracez, mais elles peuvent également être définies manuellement avec des valeurs scalaires.

Enfin, SliderLes éléments peuvent être orientés horizontalement ou verticalement. Puisqu'ils sont censés être continuellement mis à jour via un simple glissement de souris - le on_changed() La fonction est utilisée pour déclencher une réponse lorsqu'un utilisateur donne une entrée. Nous avons peaufiné le EventHandler cours avec un update() fonction qui ajuste simplement les valeurs des limites X et Y en fonction de la value des curseurs respectifs.

L'exécution de ce code produira un tracé avec deux curseurs, que nous pourrons utiliser pour modifier la portée du Axes:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Recherche verticale. Aï.

Horodatage:

Plus de Stackabuse