بوکه (Bokeh) – از صفر تا صد
«بوکه» (Bokeh)، کتابخانهای برای بصریسازی تعاملی دادهها است. برخلاف دیگر کتابخانههای موجود برای بصریسازی دادهها در «زبان برنامهنویسی پایتون»، مانند «مَتپلاتلیب» (Matplotlib) و «سیبورن» (Seaborn)، بوکه گرافیکهای خود را با استفاده از «اچتیامال» (HTML) و «جاوا اسکریپت» (JavaScript) رندر میکند. این موضوع موجب شده تا بوکه به گزینهای مناسب برای ساخت دشبوردها و اپلیکیشنهای مبتنی بر وب مبدل شود. به طور کلی باید گفت، کتابخانه بوکه ابزاری قدرتمند برای اکتشاف و درک دادهها یا ساخت نمودارهای زیبا برای پروژهها و گزارشها است. هدف از این راهنما آن است که روش کار با کتابخانه بوکه با بهرهگیری از مجموعه دادههای جهان واقعی، آموزش داده شود. سرفصلهای زیر در این مطلب ارائه شدهاند.
- تبدیل دادهها به بصریسازی با استفاده از کتابخانه Bokeh
- سفارشیسازی و مرتبسازی بصریسازیها
- افزودن قابلیت تعامل به بصریسازیها
از داده تا بصریسازی
ساخت خروجیهای بصری با استفاده از کتابخانه بوکه (Bokeh) شامل گامهای زیر میشود:
- آمادهسازی دادهها
- تعیین محل بصریسازیها (روش رندر)
- انتخاب اَشکال (Figures)
- کار با دادهها و ترسیم آنها
- سازماندهی قالبها
- پیشنمایش و ذخیره خروجیها
اکنون، هر یک از مراحل بیان شده در بالا، همراه با جزئیات بیشتر مورد بررسی قرار میگیرد.
آمادهسازی دادهها
بصریسازی دادهها همیشه با دادههای ورودی آغاز میشود. در این گام معمولا از کتابخانههای «پیشپردازش» (Preprocessing) دادهها مانند «پانداس» (Pandas) و «نامپای» (NumPy) استفاده میشود و طی آن، گامهای مورد نیاز برای تبدیل دادهها به فرم مناسب برای انجام پردازشها، برداشته میشود.
تعیین محل بصریسازیها
در این گام، چگونگی تولید و نمایش بصریسازیها، به وسیله کاربر تعیین میشود. در این راهنما، دو گزینه متداولی که بوکه در این راستا فراهم میکند ارائه شدهاند که عبارتند از: تولید یک فایل HTML استاتیک و رندر کردن بصریسازیها به صورت خطی در «ژوپیتر نوتبوک» (Jupyter Notebook).
انتخاب اَشکال
در این مرحله، اشکال (Figure) توسط کاربر تعیین و بوم اولیه برای بصریسازی دادهها آماده میشود. در گام انتخاب اشکال، میتوان همه چیز از عناوین گرفته تا علامتها را سفارشیسازی کرد. همچنین، میتوان با بهرهگیری از مجموعهای از ابزارها کاربران را قادر به تعامل با بصریسازیها کرد.
کار با دادهها و ترسیم آنها
اکنون، از قابلیت رندر کردن بوکه برای شکل دادن به دادهها استفاده میشود. در این فاز، باید از انعطافپذیری موجود برای ترسیم دادهها از پایه با استفاده از اشکال و نشانهگرهای متعدد موجود استفاده کرد؛ همه این موارد به سادگی قابل سفارشیسازی هستند. این عملکرد، آزادی فوقالعادهای را جهت ارائه دادهها در اختیار کاربر قرار میدهد. علاوه بر موارد بیان شده، بوکه دارای توابع توکاری برای ساخت چیزهایی مانند «نمودار میلهای تجمعی» (Stacked Bar Charts) و قابلیتهایی برای ساخت بصریسازیهای پیشرفتهتر مانند گرافهای شبکه و نقشهها است.
سازماندهی قالب
بوکه، برای افرادی که نیاز به بیش از یک تصویر برای تشریح دادههای خود دارند نیز ابزاری مناسب محسوب میشود. این کتابخانه، نه فقط گزینههای «قالب» (layout) شبکه مانند استاندارد را فراهم میکند، بلکه این امکان را برای کاربر فراهم میکند تا به سادگی بصریسازیها را با تنها با چند خط کد در یک قالب قرار دهد. علاوه بر آن، نمودارها را میتوان به سرعت به یکدیگر لینک کرد؛ بنابراین، انتخاب یکی از نمودارها، بر کلیه نمودارهای دیگر (هر ترکیبی از دیگر گزینهها) نیز تاثیرگذار است.
پیشنمایش و ذخیره خروجیها
در نهایت، زمان آن فرا میرسد که آنچه ساخته شده است را نمایش داد. اگرچه، بصریسازیها در مرورگر یا نوتبوک قابل مشاهده هستند، کاربر قادر به بررسی خروجیها (بصریسازیها)، سفارشیسازی آنها و ویرایش قسمتهای تعاملی موجود در آنها است. اگر کاربر آنچه که دیده را بپسندد، میتواند بصریسازیها را به صورت یک فایل تصویر (Image) ذخیرهسازی کند. در غیر این صورت (یعنی در صورتی که خروجیها نظر کاربر را جلب نکرد)، کاربر میتواند گامهای انجام شده در بالا را برای کسب خروجیهایی که در نظر دارد، مورد بازنگری قرار دهد. شش گام بیان شده در بالا، بلوکهای سازنده یک الگوی سازمانیافته و انعطافپذیر هستند که از مرحله دریافت دادهها از مجموعه داده تا ترسیم آنها به صورت نمودارهای جذاب و قابل فهم را پوشش میدهند.
یکی از قطعه کدهای متداولی که برای انجام کلیه گامهایی که پیشتر بیان شدند مورد استفاده قرار میگیرد در بالا نمایش داده شده است.
ساخت اولین تصویر با کتابخانه بوکه
راهکارهای متعددی برای ارائه خروجی بصری از دادهها در کتابخانه «بوکه» (Bokeh) وجود دارد.
در این راهنما، گزینههای معرفی شده در زیر مورد استفاده قرار میگیرند.
- ('output_file('filename.html: بصریسازیها را روی یک فایل HTML استاتیک مینویسد.
- ()output_notebook بصریسازیها را به طور مستقیم در «ژوپیتر نوتبوک» رندر میکند.
شایان ذکر است که هیچ یک از دو تابع بالا بصریسازیها را به کاربر نمایش نمیدهند. در واقع این اتفاق مادامی که ()show فراخوانی نشده نمیافتد. اگرچه، این توابع اطمینان حاصل میکنند که در صورت فراخوانی ()show، بصریسازیها به گونهای نمایش داده میشود که کاربر تمایل دارد. با فراخوانی همزمان ()output_file و ()output_notebook در یک اجرای واحد، بصریسازی هم روی فایل HTML استاتیک و هم روی نوتبوک به صورت توکار انجام میشود. اگر به هر دلیلی کاربر چند دستور ()output_file را به طور همزمان اجرا کند، تنها آخرین دستور برای رندر کردن مورد استفاده قرار میگیرد. اکنون، فرصت خوبی فراهم شده تا کد اولیه در ()figure پیشفرض بوکه با استفاده از ()output_file نوشته شود.
همانطور که مشهود است، یک پنجره جدید مرورگر باز شده که به آن Empty Bokeh Figure و empty figure گفته میشود. آنچه در تصویر مشهود نیست و در پشت صحنه به وقوع میپیوندد، ساخته شدن فایلی با نام output_file_test.html در پوشه کاری جاری کاربر است. اگر کاربر قصد داشته باشد که قطعه کدی مشابه با ()output_notebook را به جای ()output_file اجرا کند، با این فرض که Jupyter Notebook در حال اجرا است میتواند از قطعه کد زیر استفاده کند.
همانطور که مشهود است، نتایج مشابه هستند و صرفا رندر کردن در محلهای متفاوتی به وقوع پیوسته است. اطلاعات بیشتر پیرامون ()output_file و ()output_notebook در مستندات رسمی بوکه (+) موجود است. نکته شایان توجه آن است که گاهی هنگام رندر کردن چندین بصریسازی به ترتیب، مشاهده میشود که رندرهای قبلی مربوط به اجراهای پیشین پاک نشدهاند. در صورت مواجه شدن با چنین شرایطی، میتوان کد زیر را «وارد» (Import) و در میان اجراها اجرا کرد.
پیش از ادامه دادن این مطلب، لازم به ذکر است که بوکه به طور پیشفرض با یک جعبه ابزار از پیش بارگذاری شده میآید. اطلاعات بیشتر پیرامون این جعبه ابزار و چگونگی پیکربندی آن در بخش افزودن تعامل، در پایان این راهنما ارائه شده است.
آمادهسازی اولین شکل برای دادهها
اکنون که چگونگی ساخت و نمایش یک تصویر کلی بوکه هم در مرورگر و هم در ژوپیتر نوتبوک آموزش داده شد، زمان آن رسیده تا بیشتر پیرامون چگونگی پیکربنی شی ()figure توضیح داده شود. شی ()figure فقط پایه بصریسازی دادهها نیست، بلکه شیئی است که ابزارهای بوکه برای بصریسازی دادهها را قفلگشایی میکند.
figure در بوکه یک زیرکلاس از «Bokeh Plot Object» است که پارامترهای زیادی را برای پیکربندی عناصر زیباییشناختی شکل فراهم میکند. برای درک بهتر این مطلب، در ادامه زشتترین تصویر ممکن با قطعه کد زیر ساخته میشود.
هنگامی که شی ()figure معرفی شد، میتوان آن را پیکربندی کرد. اکنون، فرض میشود که کاربر میخواهد خطوط شبکهای را حذف کند. برای این کار میتوان از قطعه کد زیر استفاده کرد.
مشخصات خطوط شبکهای از طریق خصیصه grid شکل در دسترس هستند. در این مثال، تنظیم grid_line_color روی None، به شکل موثری همه خطوط شبکهای را به صورت یکباره حذف میکند.
نکته: اگر کاربر در نوتبوک یا «محیط توسعه یکپارچه» (Integrated Development Environment | IDE) با قابلیت «تکمیل خودکار» (auto-complete) کار میکند، میتواند از مزایای قابل توجه آن استفاده کند. ()figure دارای عناصر قابل سفارشیسازی متعددی است و قابلیت تکمیل خودکار برای کشف گزینههای موجود برای سفارشیسازی بسیار مفید محسوب میشود.
در صورتی که محیط توسعه مورد استفاده کاربر دارای قابلیت تکمیل خودکار نیست، انجام یک جستوجوی سریع، با کلیدواژه Bokeh و آنچه که کاربر قصد دارد انجام دهد، معمولا او را به مسیر صحیحی هدایت میکند. مطالب بسیار زیادی برای آموزش دادن در همین رابطه وجود دارند، اما ورود بیش از حد به جزئیات، این مطلب را از هدف اصلی آن دور میکند. برای مطالعه بیشتر در این رابطه، میتوان از موارد زیر استفاده کرد.
- Bokeh Plot Class (+): سوپرکلاسی از شی ()figure است که شکلها از آن خصیصههای زیادی را به ارث میبرند.
- The Figure Class (+): محل خوبی برای پیدا کردن جزئیات بیشتر پیرامون آرگومانهای شی ()figure است.
در ادامه، برخی از گزینههای سفارشیسازی خاصی که فراگیری آنها ارزشمند است بیان شدهاند.
- Text Properties (+): همه خصیصههای مربوط به تغییر استایل، سایز، رنگ و دیگر موارد مربوط به «قلم» (Font) در این قسمت تحت پوشش قرار میگیرند.
- TickFormatters (+): اشیا توکاری هستند که برای قالببندی محورها استفاده میشوند. نحو مورد استفاده برای انجام این کار، مشابه با نحو پایتون برای قالببندی رشتهها است.
گاهی، تا هنگامی که بخشی از دادهها بصریسازی نشوند، مشخص نیست که تصویر چقدر نیاز به ویرایش و سفارشیسازی دارد. بنابراین، در ادامه روش انجام این کار آموزش داده خواهد شد.
ترسیم دادهها با Glyphs
یک شکل خالی، مساله جذاب و قابل توجهی نیست؛ بنابراین در ادمه به بررسی glyphs که بلوک سازنده بصریسازیهای Bokeh است پرداخته میشود. glyph یک شکل گرافیکی برداریسازی شده یا «نشانگری» (Marker) است که برای ارائه دادهها در اشکالی مانند یک دایره یا مربع مورد استفاده قرار میگیرد.
مثالهای بیشتر در این رابطه در گالری بوکه (+) موجود هستند. پس از ساخت شکل، باید به دستهای از متدهای قابل پیکربندی glyph دسترسی داده شود. اکنون، کار با یک مثال بسیار پایهای آغاز میشود که طی آن چندین نقطه روی یک دستگاه مختصات x-y ترسیم میشوند.
پس از معرفی ()figure، میتوان دید که چگونه میتوان از آن برای ترسیم دادهها در دستگاه مختصات x-y با استفاده از glyphهای circle سفارشیسازی شده استفاده کرد. در ادامه برخی از دستههای glyph معرفی شدهاند.
- Marker شامل اشکالی مانند دایره، لوزی، مربع و مثلث است و برای ساخت بصریسازیهایی مانند «نمودارهای نقطهای» (Scatter chart) و «نمودار حبابی» (Bubble chart) مفید محسوب میشود.
- Line مواردی مانند اشکال تکخطی، خطی پلهای و چندخطی را شامل میشود که میتوان از آنها برای ساخت نمودارهای خطی استفاده کرد.
- Bar/Rectangle اشکالی هستند که برای ساخت نمودارهای میلهای سنتی یا پشتهای (hbar)، ستونی (vbar)، آبشاری و «گانت» (gantt) مورد استفاده قرار میگیرند.
glyphها را میتوان ترکیب کرد تا قابلیتهای لازم برای بصریسازی تامین شوند. اکنون فرض میشود که هدف ساخت تصویری است که تعداد کلمات نوشته شده در هر روز برای ساخت این راهنما را با یک خط نشانگر روند رشد تعداد کلمات (روزانه و تجمعی) نشان دهد.
برای ترکیب ستونها و خطها در شکل، این موارد با استفاده از شی ()figure ساخته شدهاند. علاوه بر آن، میتوان مشاهده کرد که با تنظیمات legend برای هر glyph چگونه میتوان راهنمای نمودار را به صورت یکپارچه ترسیم کرد. راهنمای نقشه نیز با تخصیص «top_left» به «fig.legend.location» به گوشه بالا و سمت راست نمودار انتقال داده میشود.
نگاهی کوتاه به دادهها
کتابخانه بصریسازی بوکه فرصت خوبی را برای کار با دادههای گوناگون فراهم میکند. جذابیت Bokeh در آن است که تقریبا پیادهسازی هر ایده بصریسازی با آن امکان دارد و این موضوع فقط به چگونگی استفاده از ابزارهایی که در اختیار کاربر قرار داده بستگی دارد.
در مثالی که در ادامه به آن پرداخته میشود از مجموعه دادههای عمومی Kaggle که مربوط به ۷۲ فصل از مسابقات بسکتبال اتحادیه ملی بسکتبال آمریکا ( the National Basketball Association’s (NBA) 2017-18 season) هستند، استفاده شده است.
- 2017-18_playerBoxScore.csv (+): آمارهای بازیکنان به صورت بازی به بازی
- 2017-18_teamBoxScore.csv (+): آمارهای تیم به صورت بازی به بازی
- 2017-18_standings.csv (+): جدول ردهبندی و امتیازات روزانه
پس از دانلود مجموعه داده، با استفاده از قطعه کدی که در ادامه آمده، دادهها در دیتافریم کتابخانه «پانداس» (Pandas) خوانده میشوند.
این قطعه کد دادهها را از سه فایل CSV خوانده و به صورت خودکار ستونهای داده را به صورت اشیا datetime تفسیر میکند. اکنون زمان آن رسیده که روی دادههای واقعی کار شود.
استفاده از شی ColumnDataSource
در مثال بالا از لیستهای پایتون و آرایههای «نامپای» (Numpy Arrays) برای نمایش دادهها استفاده شده است. کتابخانه «بوکه» (Bokeh) برای مدیریت این نوع دادهها به خوبی تجهیز شده است. اگرچه، هنگامی که بحث دادهها در پایتون میشود، احتمال استفاده از دیکشنریها و دیتافریمهای پانداس نیز وجود دارد، به ویژه اگر دادهها از یک فایل یا منبع داده خارجی خوانده میشوند. Bokeh برای کار با این ساختارهای داده پیچیدهتر توانمند و حتی دارای توابع توکاری برای مدیریت آنها است؛ به عنوان مثالی از این توابع میتوان به ColumnDataSource اشاره کرد.
اکنون، امکان دارد این پرسش مطرح شود که «اگر Bokeh دارای رابطی برای کار با دادهها به صورت مستقیم است چرا از ColumnDataSource استفاده شود؟». اولا، هنگامی که به یک لیست، آرایه یا دیتافریم به طور مستقیم ارجاع داده میشود، بوکه در پشت صحنه به هر حال آن را به یک ColumnDataSource تبدیل میکند. دوم و مهمتر آنکه، ColumnDataSource پیادهسازی قابلیتهای تعاملی بوکه را سادهتر میسازد.
ColumnDataSource در انتقال دادن دادهها به glyphهایی که برای بصریسازی مورد استفاده قرار میگیرند نقش بنیادین دارد. کارکرد اصلی آن، برای نگاشت اسامی به ستونهای دادهها است. این کار موجب میشود ارجاع به عناصر دادهها هنگام ساخت بصریسازیها آسانتر شود. این تابع همچنین انجام کار مشابهی را هنگام ساخت بصریسازیها آسانتر میکند. ColumnDataSource میتواند سه نوع شی داده بیان شده در زیر را تفسیر کند.
- Python dict: «کلیدها» (keys)، اسامی مرتبط با توالیهای مربوطه هستند (لیستها، آرایهها و به همین ترتیب).
- DataFrame پانداس: ستونهای DataFrame، اسامی مرجع برای ColumnDataSource هستند.
- groupby در پانداس: ستونهای ColumnDataSource را به شکل دیده شده با فراخوانی ()groupby.describe ارجاع میدهند.
اکنون، کار با بصریسازی مسابقات برای جایگاه اول در NBA’s Western Conference in 2017-18 برای مدافع قهرمانی یعنی تیم Golden State Warriors و رقیب آن Houston Rockets آغاز میشود. رکوردهای روزانه پیروزی-شکست برای این دو تیم در یک دیتافریم با نام west_top_2 ذخیره شده است.
از اینجا میتوان این DataFrame را در دو شی ColumnDataSource بارگذاری و مسابقه را بصریسازی کرد.
چگونگی ارجاع داده شدن اشیای ColumnDataSource هنگام ساخت دو خط قابل توجه است. اسامی ستون اصلی به سادگی به عنوان پارامترهای ورودی پاس داده میشوند و مشخص میشود که کدام ColumnDataSource با خصیصه source مورد استفاده قرار بگیرد. بصریسازیها نشانگر وجود مسابقات تنگاتنگی در این فصل و همچنین، حاکی از تاثیر قابل توجه Warriors در میانه فصل هستند. اگرچه، یک بیت لغزش در فصل پیش امکان بالا رفتن را برای Rockets فراهم کرده و در نهایت از مدافعان قهرمانی پایان فصل، به عنوان تیم اول پیشی گرفته است.
نکته: در بوکه، میتوان رنگها را بر اساس اسم، مقدار پایه ۱۶ (hex value)، یا کد رنگ RGB تعیین کرد. برای بصریسازی بالا، دو رنگ برای خطوط مربوطه تعیین شدهاند که نشانگر دو تیم هستند. به جای استفاده از اسامی رنگهای CSS، کاربر ممکن است بخواهد که با استفاده از رنگهای رسمی تیمها به صورت کدهای هگزادسیمال جلوه زیبایی به خروجیها ببخشد. در عین حال، میتوان از تاپلهایی که کدهای رنگ RGB را نشان میدهند (۲۰۶، ۱۷، ۶۵) برای Rockets و کدهای (۰، ۱۰۷ و ۱۸۲) برای Warriors استفاده کرد.
بوکه لیست مفیدی از اسامی رنگهای CSS که بر اساس فام اصلی آنها دستهبندی شدهاند را ارائه میکند. همچنین، میتوان از سایتهای متعددی که برای یافتن کدهای رنگی به صورت CSS ،RGB و hex وجود دارند، استفاده کرد. اشیای ColumnDataSource میتوانند کاری بیش از ارجاعدهی به ستونهای DataFrame انجام دهند. شی ColumnDataSource دارای سه فیلتر توکار است که میتوانند برای ساخت نمایشهایی از دادهها با استفاده از شی CDSView مورد استفاده قرار بگیرند؛ این سه فیلتر در ادامه معرفی شدهاند.
- GroupFilter کار فیلتر کردن ColumnDataSource را با استفاده از لیستی از اندیسهای صحیح (Integer) انجام میدهد.
- IndexFilter که ColumnDataSource را با استفاده از لیستی از شاخصهای صحیح فیلتر میکند.
- BooleanFilter امکان استفاده از لیستی از مقادیر boolean را با سطرهای True که انتخاب شدهاند فراهم میکند.
در مثال پیشین، دو شی ColumnDataSource ساخته شدند که هر یک از آنها زیرمجموعهای از دیتافریم west_top_2 هستند. مثال بعدی، خروجی مشابهی را از یک ColumnDataSource بر پایه west_top_2 با استفاده از GroupFilter میسازد که دیدی از دادهها فراهم میکند.
چگونگی پاس دادن GroupFilter به CDSView در یک لیست قابل توجه است. این کار، امکان ترکیب چندین فیلتر با یکدیگر را برای ایزوله کردن دادههایی که از ColumnDataSource مورد نیاز هستند فراهم میکند. Western Conference به عنوان مسابقاتی مهیج پایان یافت که رقابتهای آن حقیقتا تنگاتنگ برگزار شده بودند. این رقابتها در ادامه به صورت بصری ارائه خواهند شد. بنابراین، در ادامه به موضوع بعدی یعنی layoutها پرداخته خواهد شد.
سازماندهی بصریسازیهای متعدد با Layoutها
جدول ردهبندی Eastern Conference به دو دسته از رقابتها در بخش آتلانتیک تقسیم میشود که عبارتند از: Boston Celtics و Toronto Raptors. پیش از تکرار گامهایی که برای ساخت west_top_2 مورد استفاده قرار گرفتند، بهتر است یکبار دیگر ColumnDataSource با استفاده از آنچه پیشتر توضیح داده شد مورد آزمون قرار بگیرد.
در این مثال، چگونگی خوراک دادن کل DataFrame به یک ColumnDataSource و ساخت نمایشهایی برای ایزوله کردن دادههای مرتبط، بیان خواهد شد.
ColumnDataSource قادر به ایزوله کردن دادههای مرتبط در یک دیتافریم ۵، ۰۴۰ در ۳۹ بدون سختی قابل توجه و تنها با چند خط کد «پانداس» (Pandas) است. با نگاه به بصریسازیها، میتوان مشاهده کرد که رقابتهای Eastern Conference دارای هیچ مشکلی نیستند. پس از آنکه Celtics نتوانستند میادین را به خوبی حفظ کنند، Raptorsها همه راه را بازگشتند تا بر رقیب خود غلبه کرده و فصل را با پنج برد بیشتر به اتمام برسانند.
با دو بصریسازی آماده، زمان آن رسیده تا این نمودارها در کنار هم قرار داده شوند و تحلیلهایی روی آنها صورت پذیرد. مشابه با عملکرد subplot در «مَتپِلاتلیب» ( Matplotlib)، بوکه نیز دارای توابع column، row و gridplot در ماژول bokeh.layouts است. این توابع میتوانند به صورت عمومیتر با عنوان layout دستهبندی شوند. استفاده از این layoutها کار سختی نیست. اگر هدف، قرار دادن دو بصریسازی در پیکربندی عمودی باشد میتوان به صورت زیر عمل کرد.
تنها با تغییر column با row در قطعه کد بالا، میتوان به طور مشابه دو نمودار را به صورت افقی در کنار هم قرار داد.
نکته: برای افرادی که همراه با مطالعه این مطلب در تلاش برای نوشتن کدهای خودشان هستند، در ادامه نکاتی پیرامون خطایی که امکان دارد با آن مواجه شوند ارائه میشود. این خطا ممکن است ضمن دسترسی به west_fig و east_fig در مثالی که در ادامه ارائه شده رخ دهد. خطای مذکور، چیزی شبیه آنچه در زیر آمده، خواهد بود.
این تنها یکی از خطاهای متعددی است که به عنوان ماژول اعتبارسنجی بوکه به وقوع میپیوندند که در آن W-1004 هشداری پیرامون استفاده مجدد از west_fig و east_fig در یک layout جدید است. برای اجتناب از این خطاها، همانطور که مثالها تست میشوند، قطعه کدی که هر لایه را نمایش میدهد به صورت زیر آغاز میشود:
انجام این کار موجب نوسازی مولفههای مرتبط برای رندر کردن بصریسازیها و حصول اطمینان از این موضوع میشود که هیچ هشداری مورد نیاز نیست. به جای استفاده از column یا row، کاربر ممکن است بخواهد که از gridplot استفاده کند.
یک تفاوت کلیدی gridplot با دیگر موارد آن است که به طور خودکار نوار ابزار را در سراسر شکلهای (Figures) فرزند تحکیم میکند. همانطور که مشهود است، در gridplot به جای آنکه یک تاپل به عنوان ورودی به آن داده شود، نیازمند لیستی از لیستها است که در آن هر زیر لیست یک سطر از شبکه را نشان میدهد:
در نهایت، gridplot امکان انتقال مقادیر None را فراهم میکند که به صورت زیرنمودارهای خالی تفسیر میشوند. از این رو، اگر کاربر قصد قرار دادن یک placeholder برای دو نمودار اضافهتر را داشته باشد، میتواند به صورت زیر عمل کند.
اگر کاربر قصد جابهجایی میان بصریسازیها در سایز کامل آنها را بدون پایین کشیدن آنها برای متناسب شدن در کنار یا بر فراز هم داشته باشد، یک گزینه خوب tabbed layout است. یک tabbed layout شامل دو تابع ویجت Bokeh است: ()Tab و ()Panel از زیرماژول bokeh.models.widgets. همچون استفاده از ()gridplot، ساخت یک tabbed layout نیز کار سادهای به حساب میآید.
اولین گام، ساخت یک ()Panel برای هر tab است. این موضوع ممکن است کمی گیجکننده به نظر برسد، در واقع باید به تابع ()Tabs به عنوان مکانیزمی که Tabهای جداگانه ساخته شده با ()Panel را سازماندهی میکند نگریست. هر ()Panel یک فرزند را به عنوان ورودی دریافت میکند که میتواند یک ()figure یا layout تنها باشد. (باید به خاطر داشت که layout یک نام عمومی برای column ،row یا gridplot است.) پس از آنکه پنلها سرهم شدند، میتوان آنها را به ()Tabs در یک لیست انتقال داد. اکنون که چگونگی دسترسی، ترسیم و سازماندهی دادهها مشخص شد، زمان آن رسیده که معجزه بوکه را روی دادههای واقعی دید: تعامل!
افزودن تعامل
ویژگی که بوکه را از دیگر کتابخانههای موجود متمایز میکند، توانایی آن برای پیادهسازی آسان تعامل در بصریسازیها است.
بوکه حتی تا توصیف خودش به عنوان یک کتابخانه بصریسازی تعاملی پیش میرود.
Bokeh یک کتابخانه بصریسازی تعاملی است که مرورگرهای مدرن را برای ارائه، هدف قرار میدهد.
در این بخش، چهار راهکاریی که میتوان با استفاده از آنها تعامل را به بصریسازیها افزود بیان شدهاند.
- پیکربندی نوار ابزار
- انتخاب نقاط داده
- افزودن اقدام شناور
- پیوند دادن محورها و انتخابها
- برجسته کردن دادهها با استفاده از legend
پیادهسازی این عناصر تعاملی امکان اکتشاف دادهها را به شیوهای فراهم میکند که بصریسازیهای استاتیک نمیتوانند انجام دهند.
پیکربندی نوار ابزار
چنانکه پیشتر در بخش «ساخت شکل اولیه» بیان شد، ()figure پیشفرض بوکه با یک نوار ابزار عرضه میشود. نوار ابزار پیشفرض با ابزارهایی که در ادامه بیان شدهاند ارائه میشود (از چپ به راست).
- Pan
- Box Zoom
- Wheel Zoom
- Save
- Reset
نوار ابزار را میتوان با پاس دادن toolbar_location=None هنگام معرفی یک شی ()figure حذف کرد و یا با پاس دادن هر یک از گزینههای above، below، left یا right تغییر مکان داد. علاوه بر آن، نوار ابزار را میتوان برای در بر گرفتن هر ترکیبی از ابزارهایی که کاربر تمایل دارد پیکربندی کرد. بوکه ۱۰ ابزار اختصاصی در ۱۸ دسته ارائه می کند که در زیر بیان شدهاند.
- Pan/Drag: box_select, box_zoom, lasso_select, pan, xpan, ypan, resize_select
- Click/Tap: poly_select, tap
- Scroll/Pinch: wheel_zoom, xwheel_zoom, ywheel_zoom
- Actions: undo, redo, reset, save
- Inspectors: crosshair, hover
انتخاب نقاط داده
پیادهسازی رفتار انتخاب به سادگی افزودن چند کلیدواژه خاص هنگام اعلام glyphها است. دومین مثال، یک نمودار پراکندگی میسازد که تعداد کل ضربات سه امتیازی را نسبت به درصد ضربات ساخته شده (برای بازیکنانی با دستکم ۱۰۰ ضربه سه امتیازی) نمایش میدهد. دادهها را میتوان از دیتافریم player_stats تجمیع کرد.
در ادامه نمونهای از دیتافریمهای حاصل شده را میتوان مشاهده کرد.
name play3PA play3PM pct3PM 229 Corey Brewer 110 31 0.281818 78 Marc Gasol 320 109 0.340625 126 Raymond Felton 230 81 0.352174 127 Kristaps Porziņģis 229 90 0.393013 66 Josh Richardson 336 127 0.377976
اکنون، فرض میشود که کاربر قصد انتخاب گروهی از بازیکنان را در توزیع دارد و در این راستا رنگ glyphها که نشانگر بازیکنان انتخاب نشده هستند را خاموش میکند.
کاربر ابتدا باید ابزارهای انتخابی که میخواهد در دسترس باشند را تعیین کند. در مثال بالا، box_select، lasso_select، poly_select و tap (به علاووه دکمه reset) در لیستی که select_tools نامیده میشود تعریف شدهاند. هنگامی که شکل تعریف شد، نوار ابزار در موقعیت below در نمودار قرار میگیرد و لیست به tools برای در دسترس قرار دادن ابزارهای انتخاب شده در بالا انتقال داده میشود. هر بازیکن در ابتدا با یک مربع به رنگ آبی تیره نمایش داده میشود، اما پیکربندیهای بیان شده در زیر هنگامی که یک بازیکن یا بازیکنان انتخاب میشوند تنظیم شده است.
- تبدیل کردن بازیکنان انتخاب شده به آبی آسمانی
- تغییر glyphهای همه بازیکنان انتخاب نشده به رنگ خاکستری روشن (lightgray) با شفافیت ۰.۳
تنها با چند تغییر سریع، بصریسازی اکنون به چیزی مانند تصویر زیر مبدل شده است.
افزودن Hover
ابزار ()HoverTool اندکی با ابزارهای انتخاب شده در بالا متفاوت و دارای مشخصههایی و به ویژه tooltips است. ابتدا، میتوان یک tooltip را با ساخت لیستی از تاپلها که حاوی توصیفها و ارجاعات به ColumnDataSource هستند ساخت. این لیست به عنوان ورودی به ()HoverTool انتقال داده شده و سپس به سادگی با استفاده از ()add_tools به شکل افزوده شده است. در ادامه، آنچه به وقوع پیوسته قابل مشاهده است.
اضافه شدن دکمه Hover به جعبه ابزار قابلیت روشن و خاموش شدن را میافزاید که در تصویر بالا میتوان آن را مشاهده کرد. در صورتی که کاربر قصد تاکید بیشتر بر بازیکنان در Hover را داشته باشد، بوکه انجام این کار را با وارسی Hover امکانپذیر ساخته است. در ادامه، کد اندکی ویرایش شده از قطعه کد بالا که tooltip به آن افزوده شده، ارائه شده است.
این کار با ساخت یک glyph کاملا جدید انجام میشود، در این مثال، از دایرهها به جای مربع استفاده شده که به hover_glyph تخصیص داده شدهاند. توجه به این نکته لازم است که شفافیت اولیه برابر با صفر تعیین شده، بنابراین تا هنگامی که نشانگر موس آن را لمس نکند، به صورت شفاف است. مشخصههایی که برای hover ظاهر میشوند با تنظیم hover_alpha برابر با ۰.۵ در امتداد hover_fill_color تنظیم میشوند. اکنون، هنگام Hover کردن روی مارکرهای گوناگون، دایره کوچک مشکی روی مربع اصلی ظاهر میشود.
پیوند دادن محورها و انتخابها
پیوند دادن، فرآیند همگامسازی عناصر از بصریسازیهای گوناگون درون یک قالب است. برای مثال، ممکن است کاربر بخواهد که محورهای چند نمودار را برای اطمینان از اینکه اگر روی آنها بزرگنمایی شود روی دیگری منعکس میشوند به یکدیگر پیوند دهد.
برای این مثال، بصریسازیها قادر به Pan کردن (اسکرول افقی) به بخشهای مختلف از برنامه تیم و آزمودن وضعیت آمارهای بازیهای گوناگون هستند. آمارها به وسیله نمودار در یک ()gridplot نمایش داده میشوند. دادهها از دیتافریم team_stats قابل گردآوری هستند. در ادامه، تیم Philadelphia 76ers به عنوان تیم مورد علاقه انتخاب میشود.
در ادامه، نتایج پنج بازی اول 76ers آورده شده است.
gmDate teamPTS teamTRB teamAST teamTO opptPTS game_num winLoss 10 2017-10-18 115 48 25 17 120 1 L 39 2017-10-20 92 47 20 17 102 2 L 52 2017-10-21 94 41 18 20 128 3 L 80 2017-10-23 97 49 25 21 86 4 W 113 2017-10-25 104 43 29 16 105 5 L
کار با وارد کردن (Import) کتابخانههای لازم بوکه، مشخص کردن پارامترهای خروجی و خواندن دادهها در ColumnDataSource آغاز میشود.
هر بازی به وسیله یک ستون ارائه میشود و اگر نتیجه بُرد بود سبز و اگر باخت بود قرمز رنگ میشود. برای انجام این کار، CategoricalColorMapper بوکه، میتواند برای نگاشت مقادیر داده به رنگهای تعیین شده مورد استفاده قرار بگیرد.
برای این بررسی موردی، لیستی که مقادیر داده دستهای را نگاشت میکند به factors و لیستی با رنگهای مورد نظر به palette پاس داده میشود. چهار آمار برای بصریسازی در یک gridplot دو در دو وجود دارد که عبارتند از امتیازها (point)، پاسهای منجر به گل (assist)، ریباندها (rebounds) و گردشها (turnovers). در ساخت چهار شکل و پیکربندی نمودارهای مربوط به آنها، افزونگی زیادی در ویژگیها وجود دارد. بنابراین، برای ساده کردن کد از یک حلقه for استفاده میشود.
همانطور که مشهود است، تنها پارامترهایی که نیاز به تنظیم داشتند y-axis-label شکل و دادههایی که top را در vbar دیکته میکند هستند. این مقادیر به راحتی در یک dict ذخیره میشوند که در آن تکرار به منظور ساخت شکل برای هر آمار انجام میشود. همچنین، میتوان پیادهسازی CategoricalColorMapper در پیکربندی glyph مربوط به vbar را مشاهده کرد. خصوصیت رنگ یک ٰdict را با فیلد درون ColumnDataSource پاس میدهد تا نگاشت شود؛ بدین شکل، نام CategoricalColorMapper در بالا ساخته شده است.
دید اولیه فقط ۱۰ بازی اول از فصل 76ers را نشان میدهد، بنابراین، نیاز به راهی برای اسکرول افقی (pan horizontally) برای کاوش در کل بازیهای این فصل است. بدین ترتیب، پیکربندی نوار ابزار امکان لازم برای داشتن یک ابزار xpan که قابلیت Pan کردن از طریق نمودار را بدون داشتن هرگونه نگرانی پیرامون چولگی تصادفی در نمایش در طول محور عمودی دارد، فراهم میکند. اکنون که شکل ساخته شد، gridplot را میتوان با ارجاع به اشکالی از dict ساخته شده در بالا راهاندازی کرد.
پیوند دادن محورهای چهار نمودار به سادگی تنظیم کردن x_range برای کلیه اشکال به صورت مساوی با یکدیگر است.
برای افزودن نوار عنوان به بصریسازی، میتوان این کار را روی شکل امتیازها انجام داد، اما در صورت انجام چنین کاری، فضای شکل محدود میشود. بنابراین، یک ترفند خوب استفاده از قابلیتهای Bokeh برای تفسیر HTML جهت درج عنصر Div محسوب میشود که شامل اطلاعات عنوان است. پس از آنکه ساخته شد، به سادگی میتوان آن را با ()gridplot در قالب column ترکیب کرد.
کنار هم قرار دادن همه قسمتها منجر به ساخت شکل زیر میشود.
به طور مشابه، میتوان به سادگی انتخابهای لینک شده را در جایی که انتخاب در یک نمودار روی دیگری نیز منعکس میشود، پیادهسازی کرد. برای اینکه مشخص شود این کار به چه صورت انجام میشود، بصریسازی بعدی حاوی دو نمودار پراکندگی خواهد بود، یکی درصد ضربات دو امتیازی 76ers را در مقایسه با فیلد درصد ضربات سه امتیازی نمایش میدهد و دیگری امتیاز تیمهای 76ers را در مقایسه با امتیازهای حریف به صورت بازی به بازی نشان میدهد. هدف از این کار آن است که کاربر قادر به انتخاب نقاط داده در نمودار پراکندگی سمت چپ و همچنین، تشخیص اینکه آیا نقاط داده متناظر در نمودار سمت راست مربوط به بردها هستند یا باختها، باشد. دیتافریم برای این بصریسازی شباهت زیادی به دیتافریم مربوط به مثال اول دارد.
شکلی که دادهها به نظر میرسند:
کد لازم برای ساخت بصریسازیها به صورت زیر است:
این نمایش خوبی از قدرت موجود در استفاده از ColumnDataSource است. تا هنگامی که رندر کننده glyph (در این مثال، glyphs «دایره» (circle) برای درصدها و «مربع» (square) برای شکستها و پیروزیها) ColumnDataSource مشابهی را به اشتراک میگذارند، انتخابها به صورت پیشفرض به یکدیگر لینک میشوند. در شکل زیر نمایش آنچه بیان شد به صورت بصری ارائه شده و همانطور که مشهود است آنچه در نمودار یک سمت تصویر انتخاب میشود در سمت دیگر نیز منعکس میشود.
با انتخاب یک نمونه تصادفی از نقاط داده در ربع بالا سمت راست از نمودار پراکندگی سمت چپ، نقاط متناظر آنها در نمودار مقایسه ضربات دو امتیازی و سه امتیازی برجسته میشود. به طور مشابه، هنگامی که نقاط داده در نمودار سمت راست که مربوط به امتیاز تیمها و رقبایشان است انتخاب میشوند، نقاط داده متناظر آنها در نمودار سمت چپ نمایش داده میشود.
برجستهسازی دادهها با استفاده از Legend
این گام ما را به آخرین مثال تعاملی در این راهنما هدایت میکند: legendهای تعاملی. در بخش «ترسیم دادهها با Glyphها» مشهود بود که پیادهسازی یک legend هنگام ساخت نمودار چقدر آسان است. با استفاده از legend افزودن تعامل صرفا با تخصیص یک click_policy انجامپذیر خواهد بود. با استفاده از یک خط کد، میتوان توانایی hide یا mute کردن دادهها را با بهرهگیری از legend ایجاد کرد.
در این مثال، میتوان دو نمودار پراکندگی یکسان را دید که امتیازها و ریباندهای بازی به بازی برای James و Kevin Durant را مقایسه میکنند. تنها تفاوت آنها در این است که یکی از hide به عنوان click_policy خود و دیگری از mute برای این منظور استفاده میکند. اولین گام برای پیکربندی خروجی و راهاندازی دادهها ساخت چشماندازی برای هر بازیکن از دیتافریم player_stats است.
پیش از ساخت شکل، پارامترهای متداول در شکل، مارکرها و دادهها را میتوان در دیکشنریها تلفیق و استفاده مجدد کرد. این کار نه تنها از «افزونگی» (redundancy) در گامهای بعدی جلوگیری میکند، بلکه راه سادهای برای پیچش این پارامترها در صورت نیاز فراهم میکند.
اکنون که مشخصههای گوناگون تنظیم شدند، دو نمودار پراکندگی را میتوان به شیوه خلاصهتری ساخت که کد آن در زیر آمده است.
توجه به این نکته لازم است که mute_fig دارای یک پارامتر افزوده با عنوان muted_alpha است. این پارامتر شفافیت مارکرها را هنگامی که mute به عنوان click_policy مورد استفاده قرار میگیرد تعیین میکند. در نهایت، click_policy برای هر تصویر تنظیم و در پیکربندی افقی نمایش داده میشود.
هنگامی که legend در موقعیت خود قرار گرفت، تمام آنچه نیاز است تخصیص دادن hide یا mute به مشخصه click_policy شکل است. این کار موجب میشود legend پایهای به یک legend تعاملی مبدل شود. شایان توجه است که به ویژه برای mute، مشخصههای اضافی برای muted_alpha در glyphهای circle مربوطه برای LeBron James و Kevin Durant تنظیم شدهاند. این کار، جلوههای بصری مشتق شده از تعاملهای legend را دیکته میکند.
نتیجهگیری
در این راهنما چگونگی پیکربندی اسکریپتهای پایتون با بهرهگیری از کتابخانه بوکه، به منظور رندر کردن یک فایل HTML استاتیک یا نوتبوک ژوپیتر مورد بررسی قرار گرفت. همچنین، چگونگی نمونهسازی و سفارشیسازی شی ()figure، ساخت بصریسازیها با استفاده از glyphها، دسترسی و فیلتر دادهها با ColumnDataSource، سازماندهی نمودارها در لایوتهای شبکهای و tab شده و همچنین، افزودن اشکال گوناگونی از تعامل شامل انتخاب، hover کردن، پیوند دادن و افزودن Legendهای تعاملی آموزش داده شد.
اگر نوشته بالا برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی پایتون Python
- آموزش تکمیلی برنامهنویسی پایتون
- مجموعه آموزشهای دادهکاوی و یادگیری ماشین
- زبان برنامهنویسی پایتون (Python) — از صفر تا صد
- یادگیری علم داده (Data Science) با پایتون — از صفر تا صد
- تنسورفلو (TensorFlow) — از صفر تا صد
- 1۰ کتابخانه پایتون علم داده — راهنمای کاربردی
- 13 کتابخانه یادگیری عمیق پایتون — راهنمای کاربردی
- آموزش پایتون: ساخت نمودارهای مالی با Bokeh — از صفر تا صد
^^