Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Matplotlib-widgets

Matplotlib is niet alleen voor statische plots. Hoewel GUI's doorgaans worden gemaakt met GUI-bibliotheken en raamwerken zoals PyQt, Tkinter, kivy en wxPython, en hoewel Python een uitstekende integratie heeft met PyQt, Tkinter en wxPython – het is niet nodig om deze te gebruiken voor bepaalde basis GUI-functionaliteit, via Matplotlib-widgets.

De matplotlib.widgets module heeft verschillende klassen, waaronder de AxesWidget, waaruit Buttons, CheckButtons, Sliders, TextBoxes, enz. zijn afgeleid. Deze accepteren allemaal de Axes ze worden toegevoegd als het enige verplichte constructorargument, en hun positionering moet handmatig worden ingesteld. Een ding om op te merken is dat de widget zijn de assen, dus je maakt een Axes exemplaar voor elke widget.

Een ander ding om op te merken is dat je moet verwijzingen naar de widgets behouden anders kunnen ze afval laten ophalen.

Elk van hen kan ook worden uitgeschakeld door in te stellen active naar FalseIn dat geval reageren ze niet op gebeurtenissen, bijvoorbeeld als er op wordt geklikt. Dat gezegd hebbende, kunnen we een nieuw soort interactiviteit in onze plots introduceren, via verschillende GUI-elementen en componenten.

Opmerking: Matplotlib is niet bedoeld om te worden gebruikt voor het maken van GUI's van hoge kwaliteit, noch voor gebruiksvriendelijke systemen. Deze widgets zijn rudimentair, zien er niet echt geweldig uit en hebben een beperkte functionaliteit. Ze zijn bedoeld als een manier om prototypes te maken en dingen uit te testen, in plaats van ze daadwerkelijk te verzenden.

Als je eerder met PyQt hebt gewerkt, zul je merken dat de algemene syntaxis en aanpak voor het toevoegen van deze widgets, en het verbinden ervan met gebeurtenishandlers, redelijk bekend is.

Knoppen toevoegen

Laten we beginnen met knoppen - De matplotlib.widgets module definieert een Button klas. Om er verbinding mee te maken, noemen we de on_clicked() functie, die de functie uitvoert die wij leveren. Zodra een klik wordt gedetecteerd, wordt de functie uitgevoerd.

Bij het maken van de knop wijzen we een Axes eraan, gebruikt voor positionering. We kunnen ook passeren in een label op dat moment om wat tekst toe te voegen en deze voor een gebruiker te annoteren. De color en hovercolor argumenten definiëren de kleur van de knop voor en nadat er met de muis overheen wordt bewogen.

Omdat wij voor de positionering en ruimte voor alle widgets zorgen, maken we een Figure en Axes, laat onderaan wat ruimte vrij om een ​​knop toe te voegen en teken een leeg spreidingsdiagram. Vervolgens definiëren we een EventHandler klasse, die één enkele methode heeft add_random(). De methode genereert twee willekeurige getallen en plaatst er een markering voor op het Axes we hebben eerder gemaakt en oproepen plt.draw(), die de Figure. Bij het bijwerken van percelen moeten we altijd even bellen plt.draw() nogmaals om het daadwerkelijk bij te werken:

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

Dit resulteert in een Figure, met een lege Axes binnenkant ervan en een eigen knop in de rechterbovenhoek van het scherm Axes:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

En na een paar dozijn keer op de knop te hebben gedrukt, onze ax wordt gevuld met willekeurige markeringen:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

In meer praktische termen zouden we een cyclus van functies die bij elke druk op de knop in kaart worden gebracht. Dit vereist een paar aanpassingen aan de EventHandler, evenals een andere knop om terug door die cyclus te gaan.

Laten we de Kwaliteit van rode wijn dataset opnieuw, en visualiseer verschillende functies tegen de Alcohol functie. Omdat we niet de moeite kunnen nemen om deze afzonderlijk uit te zetten, door de code te schrijven om het ene kenmerk tegen het andere uit te zetten, en vervolgens die code te wijzigen om een ​​ander kenmerk tegen het andere uit te zetten.

Het maken van een spreidingsmatrix zou ons hier kunnen helpen, maar als de dataset veel functies heeft, zal deze tamelijk onleesbaar zijn en komen we niet ver. Als je dat graag wilt hebben zowel grootschalige plots die u gemakkelijk kunt bekijken en interpreteren, . omdat er zonder extra moeite meerdere functies doorlopen – u kunt dit proces automatiseren met knoppen:

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

De EventHandler klasse heeft nu twee methoden – next_feature() en previous_feature(). Beide controleren of de teller i het einde of begin van de kolommenlijst heeft bereikt – en om een IndexError, resetten we de index naar de tegenovergestelde waarde en simuleren we a cyclus. Hieronder gaan 0 brengt ons terug naar de einde van de kolommenlijst, en als we boven de laatste kolom gaan, keren we terug naar de eerste.

Nadat we hebben vastgesteld waar we ons bevinden – wij ruim het op Axes, omdat we opnieuw bovenop een bestaand perceel zouden gaan plotten zonder het via te ontruimen cla() (cloor ax). Je kunt ook functierelaties opstapelen, door over elkaar heen te plotten en de cla() statement bij het resetten van de index aan het einde/begin van de cyclus.

Na het wissen van het Axes – we hebben een leeg canvas om op te schilderen met de ax.scatter() functie. In dit voorbeeld is de vaste functie Alcohol, zodat deze altijd aanwezig is. De andere functie varieert en is toegankelijk via iloc[], waarbij de index van de kolom wordt doorgegeven. Dit retourneert een Series die we in dit plot kunnen gebruiken. Op dezelfde manier hebben wij toegang kolom namen ook via hun index – df.columns[index], dat wordt gebruikt om het Y-aslabel in te stellen.

Ten slotte verhogen/verlagen we de teller en bellen plt.draw() om de Figure:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Zodra we op het Volgende functie knop, wordt het volgende object in de lijst met kolommen uitgezet AlcoholEn Figure zullen op passende wijze worden bijgewerkt – de labels, markeringen en schaal. Andersom geldt hetzelfde – Vorige functie zal de lijst in de tegenovergestelde richting doorkruisen, waardoor we heen en weer kunnen fietsen, met een veiligheidsmechanisme dat onze teller opnieuw instelt telkens wanneer we het einde of het begin van de cyclus bereiken.

Keuzerondjes en selectievakjes toevoegen

Radio knoppen worden gebruikt om een ​​gebruiker de mogelijkheid te geven te selecteren één waarde van meerdere waarden. Er kan slechts één keuzerondje tegelijk worden geselecteerd, en deze vertegenwoordigen doorgaans een keuze. Vink vakjes aan kan worden gebruikt als u de gebruiker meerdere opties tegelijk wilt laten selecteren.

Opmerking: Er is een zeer beperkte mogelijkheid om te controleren of er een selectievakje is on or korting. In feite is er niets uit de doos. U kunt alleen controleren of de doos dat wel is geperst or niet, wat een ernstige beperking vormt voor de manier waarop het kan worden gebruikt, omdat we geen idee hebben in welke staat het daarvoor was. Het enige alternatief is om je eigen teller/controle van de huidige status van de box bij te houden met een booleaanse waarde, en op basis daarvan de logica te wijzigen.

Hierdoor kunt u bijvoorbeeld voor elk een selectievakje toevoegen maatwerk-argument van een bepaald plot, waardoor de gebruiker deze kan instellen True or False (aangevinkt of niet aangevinkt), of enige andere niet-conflicterende mapping op basis van deze toestanden.

Maar omdat de API zelf beperkt is, beperken we ons ook tot het beoogde gebruik: dingen in- en uitschakelen. We hebben twee functies die we kunnen omdraaien on en korting via een selectievakje. Merk op dat zelfs deze functionaliteit beperkt is tot objecten waarvan u kunt controleren of ze zichtbaar zijn of niet.

Aan de andere kant willen we de gebruiker niet toestaan ​​twee schalen tegelijk toe te passen, of twee X-limieten tegelijk in te stellen, omdat alleen de instructie die tweede in de reeks wordt genoemd, zou worden toegepast. Hiervoor zouden we keuzerondjes gebruiken.

Laten we een paar keuzerondjes toevoegen zodat de gebruiker het asbereik kan selecteren via een paar keuzerondjes, maar ook de visualisaties van functies kan inschakelen on en korting:

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

Nogmaals, we hebben twee methoden in de EventHandler() klas - set_range() en apply_features(). De set_range() methode stelt het bereik in op “klein” of “groot”, door de Axes' X- en Y-limieten. De apply_features() functie verandert de visible veld van de lijndiagrammen die we eerder hebben gemaakt, op basis van hun stroom visible toestand. Als visible == True, schakelen we de Lijnplot uit, en omgekeerd.

We moeten vertrouwen op de ingebouwde mogelijkheid om de zichtbaarheid van lijndiagrammen te controleren, omdat we niet kunnen controleren of het selectievakje eerder al dan niet is aangevinkt. Ditzelfde vermogen kan worden nagebootst met een status boolean in het bereik van de EventHandler() klasse, waarop is ingesteld True en False bij elke klik, voor plottypen die geen ondersteuning bieden voor het controleren of ze out-of-the-box zichtbaar zijn.

Het uitvoeren van deze code resulteert in een Figure met twee sets knopen aan de onderkant. Als we beide selectievakjes aanvinken, verschijnen beide lijndiagrammen:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

We kunnen ze afzonderlijk uitschakelen:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

En we kunnen het bereik van de Axes via de keuzerondjes:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Tekstvakken toevoegen

Tekstvakken zijn gewend aan verzamelen gegevens van de gebruiker – en we kunnen de plots aanpassen op basis van deze gegevens. We kunnen een gebruiker bijvoorbeeld vragen om de naam van een object in te voeren, of om een ​​functie in te voegen die onze plot kan visualiseren. Natuurlijk kan het werken met gebruikersinvoer lastig zijn; er zijn altijd randgevallen waar u op moet letten.

Laten we een script schrijven waarmee de gebruiker een functienaam van een dataset, en de Axes updates van elke inzending om de input weer te geven. Voor het gemak van de gebruiker laten we hem of haar weten als de invoer niet kan worden gekoppeld aan een kolomnaam:

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

We hebben een eenvoudige controle om te zien of dit het geval is feature_name is leeg of NoneIn dat geval doen wij niets. Indien dit niet het geval is, controleren wij of de feature_name is aanwezig in de DataFrame, waarbij een bericht wordt bijgevoegd dat de functie niet is gevonden als deze niet aanwezig is. Voordat we de tekst bijvoegen, moeten we er echter voor zorgen dat het vorige bericht wordt verwijderd, zodat het nieuwe er niet mee overlapt. De axes.texts eigenschap is een lijst van alle Text exemplaren op een Axes. Sinds de Axes heeft al een Text bijvoorbeeld behorend tot onze TextBox, we willen niets verwijderen als er 2 of minder zijn Text aanwezige exemplaren – de foutmelding en de TextBox label.

Als er meer dan twee zijn, hebben we al een foutmelding, die verwijderd moet worden.

Als de functie is Aanwezig in de DataFrame, maar we ruimen de Axes en plot het:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Bereikkiezers toevoegen

Bereikkiezers kan worden gebruikt om de gebruiker in staat te stellen een reeks gegevens te selecteren en daarop te focussen, waarbij de aslimieten worden ingesteld op basis van die selectie. Standaard ondersteunen veel bibliotheken deze functionaliteit, maar helaas doet Matplotlib dat niet en zullen we dit handmatig moeten doen. Bovendien zullen we een extra moeten toevoegen "Reset" knop als we dat willen uitzoomen .

Om een ​​toe te voegen Bereikkiezer, hoeven we geen geheel nieuwe te wijden Axes daarvoor – we kunnen het aan een bestaande koppelen, wat heel logisch is. Bij het genereren van een SpanSelector, wij leveren de Axes het hoort bij, evenals de gebeurtenishandler, gevolgd door 'horizontal' or 'vertical', die de Axes en Bereikkiezer beide.

De useblit argument is doorgaans ingesteld op True omdat het de prestaties op de meeste backends verbetert. Daarnaast hebben we een aantal stijleigenschappen toegevoegd, zoals het instellen van de alpha van de rechthoek die als bereikkiezer is gemaakt 0.5 en facecolor naar een leuk 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()

Als u dit uitvoert, wordt een plot gegenereerd waarop we overspanningen kunnen selecteren en daarop kunnen inzoomen door de Axes-limits in te stellen op de opgegeven waarden:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Schuifregelaars toevoegen

Sliders stellen gebruikers in staat intuïtief tussen vele waarden te kiezen door een markering te verschuiven en een waarde te selecteren. Normaal gesproken worden schuifregelaars gebruikt om continu een bepaalde waarde in een plot bij te werken, zoals het bereik ervan or zelfs een kenmerk. U kunt bijvoorbeeld de waarde van een constante aanpassen via een schuifregelaar, die op zijn beurt invloed heeft op een functie die afhankelijk is van die constante.

Laten we een script schrijven waarmee we de Y- en X-aslimieten kunnen wijzigen via een schuifregelaar, waardoor we het perspectief kunnen veranderen van waaruit we onze gegevens bekijken:

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

We hebben de vulling aangepast om een ​​schuifregelaar aan de linkerkant en onderkant van het scherm mogelijk te maken Axesen tekende een eenvoudige lijnplot. Als we een schuifregelaar willen toevoegen, moeten we een Axes ervoor, zoals bij de meeste andere widgets, en wijs het toe aan de ax argument van de Slider via de constructeur. Bovendien kunnen we de minimum-, maximum- en beginwaarden van de schuifregelaar instellen. Dit zijn doorgaans dynamische bereiken, gebaseerd op de gegevens die u plot, maar u kunt ook handmatig scalaire waarden instellen.

Tenslotte Sliders kunnen horizontaal of verticaal worden georiënteerd. Omdat het de bedoeling is dat ze voortdurend worden bijgewerkt via een muisbeweging – de on_changed() functie wordt gebruikt om een ​​reactie te activeren wanneer een gebruiker invoer geeft. We hebben de aangepast EventHandler klasse met een update() functie die eenvoudigweg de waarden van de X- en Y-limieten aanpast op basis van de valgebruik van de respectievelijke schuifregelaars.

Het uitvoeren van deze code zal een plot opleveren met twee schuifregelaars, die we kunnen gebruiken om de reikwijdte van de Axes:

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Matplotlib Widgets PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Tijdstempel:

Meer van Stapelmisbruik