Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

ווידג'טים של Matplotlib

Matplotlib הוא לא רק עבור עלילות סטטיות. בעוד ש-GUI נוצרים בדרך כלל עם ספריות ומסגרות GUI כגון PyQt, טקינטר, קיווי ו wxPython, ובעוד של-Python יש אינטגרציה מצוינת עם PyQt, Tkinter ו wxPython - אין צורך להשתמש באף אחד מאלה עבור פונקציונליות GUI בסיסית, דרך ווידג'טים של Matplotlib.

השמיים matplotlib.widgets למודול יש מספר כיתות, כולל AxesWidget, מתוכם Buttons, CheckButtons, Sliders, TextBoxes וכו' נגזרים. כל אלה מקבלים את Axes הם מתווספים כארגומנט הבנאי האחד והיחיד, ויש להגדיר את המיקום שלהם באופן ידני. דבר שיש לציין הוא שה יישומון הוא הצירים, אז תיצור Axes מופע עבור כל ווידג'ט.

דבר נוסף שיש לציין הוא אתה צריך לשמור הפניות לווידג'טים אחרת, הם עלולים לאסוף אשפה.

כל אחד מהם יכול גם להיות מושבת על ידי הגדרה active ל False, במקרה זה, הם לא יגיבו לאירועים כלשהם, כגון לחיצה עליו. עם זאת, אנו יכולים להציג סוג חדש של אינטראקטיביות למגרשים שלנו, באמצעות אלמנטים ורכיבים GUI שונים.

הערה: Matplotlib לא נועד לשמש ליצירת GUI באיכות גבוהה, וגם לא מערכות ידידותיות למשתמש. הווידג'טים האלה הם בסיסיים, לא ממש נראים נהדר ויש להם פונקציונליות מוגבלת. הם נועדו כדרך לאבטיפוס ולבדוק דברים, במקום לשלוח אותם בפועל.

אם עבדת בעבר עם PyQt - אולי תשים לב שהתחביר הכללי והגישה להוספת ווידג'טים אלה, כמו גם חיבורם למטפלי אירועים מוכרים למדי.

הוספת כפתורים

נתחיל עם כפתורים - ה matplotlib.widgets המודול מגדיר א Button מעמד. כדי להתחבר אליו, אנו קוראים ל- on_clicked() function, אשר מבצעת את הפונקציה שאנו מספקים. לאחר זיהוי קליק, הפונקציה מופעלת.

בזמן יצירת הכפתור, אנו מקצים Axes אליו, משמש למיצוב. אנחנו יכולים לעבור גם ב label באותו זמן, כדי להוסיף קצת טקסט ולהעיר אותו עבור משתמש. ה color ו hovercolor ארגומנטים מגדירים את צבע הכפתור לפני ואחרי הרחף מעליו.

מכיוון שאנו דואגים למיצוב ולמקום לכל הווידג'טים – בואו ניצור א Figure ו Axes, אפשר קצת מרווחים בתחתית כדי להוסיף כפתור, ולתכנן עלילת פיזור ריקה. לאחר מכן, נגדיר א EventHandler class, שיש לה שיטה אחת add_random(). השיטה מייצרת שני מספרים אקראיים, ומשרטטת סמן עבורם על Axes יצרנו בעבר ומתקשרים plt.draw(), אשר מצייר מחדש את Figure. בעת עדכון מגרשים, תמיד נצטרך להתקשר plt.draw() שוב כדי לעדכן אותו בפועל:

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

התוצאה היא א Figure, עם ריק Axes בתוכו וכפתור בפינה הימנית העליונה של המסך, משלו Axes:

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

ואחרי לחיצה על הכפתור כמה תריסר פעמים, שלנו ax יאוכלס בסמנים אקראיים:

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

במונחים מעשיים יותר, נוכל ליצור א מחזור של תכונות להתוות בכל לחיצה על כפתור. זה דורש כמה שינויים ב- EventHandler, כמו גם כפתור נוסף כדי לחזור למחזור זה.

בואו נשתמש ב- איכות יין אדום שוב מערך הנתונים, ודמיין כמה תכונות מול ה כּוֹהֶל תכונה. מכיוון שאנחנו לא יכולים להיות מוטרדים לשרטט את אלה בנפרד על ידי כתיבת הקוד כדי לשרטט תכונה אחת מול האחרת, ואז לשנות את הקוד הזה כדי לתכנן תכונה אחרת מול האחרת.

יצירת מטריצת פיזור עשויה לעזור לנו כאן, אבל אם למערך הנתונים יש הרבה תכונות, הוא יהיה די בלתי קריא ולא נגיע רחוק. אם תרצה לקבל שניהם עלילות בקנה מידה גדול שתוכלו לראות ולפרש בקלות, גם כן כיוון שיש לך תכונות מרובות שעוברות על אופניים ללא כל מאמץ נוסף - אתה יכול להפוך את התהליך הזה לאוטומטי באמצעות לחצנים:

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

השמיים EventHandler לכיתה יש כעת שתי שיטות - next_feature() ו previous_feature(). שני אלו בודקים אם המונה i הגיע לסוף או להתחלה של רשימת העמודות - וכדי להימנע מ- IndexError, אנו מאפסים את האינדקס לערך ההפוך ומדמים את a מחזור. הולך למטה 0 יחזיר אותנו ל סוף של רשימת העמודות, ומעבר מעל העמודה האחרונה יחזיר אותנו לעמוד הראשון.

לאחר שביררנו היכן אנו נמצאים - אנחנו לנקות את Axes, שכן היינו מתכננים שוב על גבי עלילה קיימת מבלי לנקות אותה באמצעות cla() (clהאוזן axes). לחלופין, אתה יכול להעלות גם קשרי תכונה, על ידי ציור זה על גבי זה ולהשתמש ב- cla() הצהרה בעת איפוס האינדקס בסוף/תחילת המחזור.

לאחר ניקוי ה Axes - יש לנו קנבס מסודר לצייר עליו ax.scatter() פוּנקצִיָה. בדוגמה זו, התכונה הקבועה היא כּוֹהֶל, כך שהוא נוכח בכל עת. התכונה האחרת משתנה וניתן לגשת אליה דרך iloc[], עובר באינדקס של העמודה. זה מחזיר א Series שאנחנו יכולים להשתמש בעלילה הזו. באופן דומה, אנו יכולים לגשת שמות העמודות גם דרך המדד שלהם - df.columns[index], המשמש להגדרת התווית של ציר ה-Y.

לבסוף, אנחנו מגדילים/מקטינים את המונה ומתקשרים plt.draw() לעדכון ה- Figure:

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

ברגע שנלחץ על התכונה הבאה כפתור, הפיצ'ר הבא ברשימת העמודות יתוכנן נגדו כּוֹהֶל, וה Figure יעודכנו כראוי - התוויות, הסמנים והקנה מידה. כך גם הפוך - תכונה קודמת יחצה את הרשימה בכיוון ההפוך, ויאפשר לנו לרכוב קדימה ואחורה, עם מנגנון בטיחות שמאפס את המונה שלנו בכל פעם שנגיע לסוף או לתחילת המחזור.

הוספת לחצני רדיו ותיבות סימון

כפתורי רדיו משמשים כדי לאפשר למשתמש לבחור ערך אחד מתוך מספר ערכים. ניתן לבחור רק לחצן בחירה אחד בכל פעם, והם בדרך כלל מייצגים בחירה. תיבות סימון ניתן להשתמש אם תרצה לאפשר למשתמש לבחור אפשרויות מרובות בו-זמנית.

הערה: יש יכולת מוגבלת מאוד לבדוק אם תיבת סימון כן on or כבוי. למעשה, אין אף אחד מחוץ לקופסה. אתה יכול רק פעם לבדוק אם התיבה היא לחוץ or לֹא, מה שמהווה מגבלה רצינית לאופן השימוש בו מכיוון שאין לנו מושג באיזה מצב הוא היה לפני כן. האלטרנטיבה היחידה היא לשמור על מונה משלך/בדוק לגבי המצב הנוכחי של התיבה עם ערך בוליאני, ולשנות את ההיגיון על סמך זה.

זה יאפשר לך, למשל, להוסיף תיבת סימון לכל אחד מהם ארגומנט התאמה אישית של עלילה מסוימת, מה שמאפשר למשתמש להגדיר אותם True or False (מסומן, או לא מסומן), או כל מיפוי אחר שאינו סותר המבוסס על מצבים אלה.

עם זאת, מכיוון שה-API מוגבל בעצמו, נגביל את עצמנו גם לשימוש המיועד - הפעלה וכיבוי של דברים. יהיו לנו שתי תכונות שנוכל להפוך אותן on ו כבוי באמצעות תיבת סימון. שים לב שאפילו פונקציונליות זו מוגבלת לאובייקטים שעבורם אתה יכול לבדוק אם הם גלויים או לא.

מצד שני, אנחנו לא רוצים לאפשר למשתמש להחיל שני סולמות בבת אחת, או להגדיר שני גבולות X בבת אחת, מכיוון שרק ההצהרה שנקראת second ברצף תיושם. עבור אלה - נשתמש בלחצני רדיו.

בואו נוסיף כמה לחצני רדיו כדי לאפשר למשתמש לבחור את טווח הציר באמצעות כמה לחצני רדיו, אך גם לאפשר להם להפוך הדמיות תכונות on ו כבוי:

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

שוב, יש לנו שתי שיטות ב EventHandler() מעמד - set_range() ו apply_features(). ה set_range() השיטה מגדירה את הטווח ל"קטן" או "גדול", על ידי התאמת ה- Axes' גבולות X ו-Y. ה apply_features() הפונקציה משנה את visible שדה של עלילות הקו שעשינו קודם לכן, בהתבסס על הנוכחי שלהם visible סטָטוּס. אם visible == True, אנו מכבים את עלילת הקו, ולהיפך.

עלינו להסתמך על היכולת המובנית לבדוק את הנראות של Line Plots, שכן איננו יכולים לבדוק אם תיבת הסימון סומנה או לא קודם לכן. ניתן לחקות את אותה יכולת עם a status בוליאני בהיקף של EventHandler() מחלקה, אשר מוגדרת ל True ו False בכל קליק, עבור סוגי עלילה שאינם תומכים בבדיקה אם הם גלויים מחוץ לקופסה.

הפעלת קוד זה מביאה ל-a Figure עם שני סטים של כפתורים בתחתית. אם נסמן את שתי תיבות הסימון, שתי עלילות השורות יופיעו:

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

אנחנו יכולים לכבות אותם בנפרד:

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

ואנחנו יכולים לשנות את הטווח של Axes דרך לחצני הרדיו:

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

הוספת תיבות טקסט

תיבות טקסט משמשים לגבות נתונים מהמשתמש - ואנחנו יכולים לשנות את החלקות על סמך הנתונים האלה. לדוגמה, אנו יכולים לבקש ממשתמש להזין שם של תכונה, או להכניס פונקציה כדי שהעלילה שלנו תוכל להמחיש. כמובן, עבודה עם קלט משתמש יכולה להיות מסובכת - תמיד יש מקרי קצה שצריך לשים לב אליהם.

בואו נכתוב סקריפט שמאפשר למשתמש להזין א שם תכונה של מערך נתונים, וה- Axes עדכונים על כל הגשה כדי לשקף את הקלט. לנוחיות המשתמש, נודיע לו אם לא ניתן להתאים את הקלט לשם עמודה:

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

יש לנו בדיקה פשוטה כדי לראות אם המסופק feature_name הוא ריק או None, במקרה זה, אנחנו לא עושים כלום. אם לא, אנו בודקים אם feature_name נמצא ב DataFrame, מצרף הודעה שהתכונה לא נמצאה אם ​​היא לא קיימת. עם זאת, לפני שמצרפים את הטקסט, עלינו לוודא שההודעה הקודמת מוסרת, כדי שההודעה החדשה לא תחפוף אליה. ה axes.texts נכס הוא רשימה של כל Text מקרים על an Axes. מאז Axes יש כבר א Text למשל, שייך לשלנו TextBox, אנחנו לא רוצים להסיר שום דבר אם יש 2 או פחות Text מופעים קיימים - הודעת השגיאה וה- TextBox תווית.

אם מעל שניים, כבר קיבלנו הודעת שגיאה, אותה יש להסיר.

אם התכונה is נוכח ב DataFrameעם זאת, אנו מנקים את Axes ולתכנן את זה:

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

הוספת בוררי טווח

בוררי טווח ניתן להשתמש כדי לאפשר למשתמש לבחור טווח של נתונים ולהתמקד בו, להגדיר את גבולות הציר בהתבסס על בחירה זו. כברירת מחדל, ספריות רבות תומכות בפונקציונליות זו, אם כי למרבה הצער, Matplotlib לא עושה זאת ונצטרך לעשות זאת באופן ידני. בנוסף, נצטרך להוסיף תוספת "אִתחוּל" כפתור אם נרצה להקטין את התצוגה גם כן.

כדי להוסיף א בורר טווח, אנחנו לא צריכים להקדיש חדש לגמרי Axes בשביל זה - אנחנו יכולים לצרף אותו לקיים, וזה הגיוני מאוד. בעת יצירת א SpanSelector, אנו מספקים את Axes הוא שייך, כמו גם למטפל באירועים, ואחריו 'horizontal' or 'vertical', אשר מסובב את Axes ו בורר טווחים שניהם.

השמיים useblit ארגומנט מוגדר בדרך כלל ל True מכיוון שהוא משפר את הביצועים ברוב הקצה האחורי. בנוסף, הוספנו כמה מאפייני סטיילינג, כגון הגדרת ה alpha של המלבן שנוצר כבורר טווח ל 0.5 ו facecolor לנחמד 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()

הפעלת זה יוצרת עלילה שעליה נוכל לבחור טווחים ולהתקרב אליהם על ידי הגדרת מגבלות הצירים לערכים שסופקו:

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

הוספת סליידרים

המחוונים אפשר למשתמשים לבחור בין ערכים רבים באופן אינטואיטיבי על ידי החלקת סמן ובחירת ערך. בדרך כלל, המחוונים משמשים כדי לעדכן באופן רציף ערך כלשהו בחלקה, כגון הטווח שלה or אפילו תכונה. לדוגמה, אתה יכול להתאים את הערך של קבוע דרך מחוון, אשר בתורו משפיע על פונקציה המסתמכת על אותו קבוע.

בואו נכתוב סקריפט שמאפשר לנו לשנות את גבולות ציר ה-Y וה-X, באמצעות סליידר, שיאפשר לנו לשנות את הפרספקטיבה שממנה אנו רואים את הנתונים שלנו:

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

התאמנו את הריפוד כדי לאפשר מחוון בצד שמאל ותחתון של Axes, ושרטט עלילת קו פשוטה. הוספת סליידר מחייבת אותנו ליצור an Axes עבורו, כמו ברוב הווידג'טים האחרים, והקצה אותו ל- ax טיעון של Slider דרך הקונסטרוקטור. בנוסף, אנו יכולים להגדיר את ערכי המינימום, המקסימום וההתחלתיים של המחוון. אלה יהיו בדרך כלל טווחים דינמיים, המבוססים על הנתונים שאתה משרטט, אך ניתן גם להגדיר באופן ידני ערכים סקלרים.

לבסוף, Sliders יכול להיות מכוון אופקית או אנכית. מכיוון שהם אמורים להתעדכן ללא הרף באמצעות החלקת עכבר - ה on_changed() הפונקציה משמשת להפעלת תגובה כאשר משתמש נותן קלט. שיפרנו את EventHandler כיתה עם update() פונקציה שפשוט מתאימה את הערכים של מגבלות X ו-Y בהתבסס על value של המחוונים המתאימים.

הפעלת קוד זה תיצור עלילה עם שני סליידרים, שנוכל להשתמש בהם כדי לשנות את היקף ה- Axes:

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

Matplotlib Widgets PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

בול זמן:

עוד מ Stackabuse