بخش اول: شروع به کار
پیچیدهترین تحلیلهای آماری بدون ابزار مؤثر برای انتقال نتایج میتواند بیمعنی باشد. نتایج را اگر نتوان به وضوح بیان کرد تأثیر کمی خواهند داشت، و اغلب بهترین راه برای ارائه نتایج تجزیه و تحلیل، مصورسازی است.
منابع موجود برای علم داده به ویژه در حوزه مصورسازی به سرعت در حال پیشرفت هستند. با همه این پیشرفتها یک روند مشترک وجود دارد: افزایش تعامل.
مردم دوست دارند دادهها را در نمودارهای ایستا ببینند، اما چیزی که بیشتر از آن لذت میبرند، بازی با دادهها است تا ببینند تغییر پارامترها چگونه بر نتایج تأثیر میگذارد. در تصویر زیر میتوانید یک نمودار تعاملی را ببینید:
مصورسازی داده با Bokeh — اصول اولیه Bokeh
مفهوم اصلی Bokeh این است که نمودارها در یک زمان در یک لایه ساخته میشوند. کار را با ایجاد یک شکل شروع میکنیم و سپس عناصری به نام Glyphs را به شکل اضافه میکنیم. (برای کسانی که از ggplot در R استفاده کردهاند، ایده گلیفها (glyphs) اساساً مانند ژئومهایی است که هر بار به یک لایه به یک نمودار اضافه میشوند) Glyphs بسته به کاربرد مورد نظر میتوانند اشکال مختلفی مانند: دایره، خطوط، میلهها (Bars)، کمانها و غیره به خود بگیرند.
هم رویش منتشر کرده است:
آموزش پایتون از صفر --- برنامه نویسی مقدماتی تا پیشرفته Python
با ساختن یک نمودار اصلی با مربع و دایره، مفهوم حروف را نشان میدهیم. ابتدا با استفاده از متد figure یک نمودار میسازیم و سپس با فراخوانی متد مناسب و ارسال داده، Glyphs خود را به نمودار اضافه میکنیم. در نهایت، نمودار را نشان میدهیم (در اینجا از یک نوتبوک Jupyter استفاده میکنیم که این امکان را میدهد در صورت استفاده از فراخوانی output_notebook، نمودارها را دقیقاً زیر کد مشاهده کنیم).
from bokeh.plotting import figure
from bokeh.io import show, output_notebook
# Create a blank figure with labels
p = figure(plot_width = 600, plot_height = 600,
title = 'Example Glyphs',
x_axis_label = 'X', y_axis_label = 'Y')
# Example data
squares_x = [1, 3, 4, 5, 8]
squares_y = [8, 7, 3, 1, 10]
circles_x = [9, 12, 4, 3, 15]
circles_y = [8, 4, 11, 6, 10]
# Add squares glyph
p.square(squares_x, squares_y, size = 12, color = 'navy', alpha = 0.6)
# Add circle glyph
p.circle(circles_x, circles_y, size = 12, color = 'red')
# Set to output the plot in the notebook
output_notebook()
# Show the plot
show(p)
این کد نمودار زیر را ایجاد میکند:
در حالی که میتوانستیم به راحتی این نمودار را در هر کتابخانه ترسیمی دیگر بسازیم، چند ابزار را به صورت رایگان با هر طرح Bokeh در سمت راست دریافت میکنیم که شامل قابلیتهای استخراج، بزرگنمایی، انتخاب و ذخیره نمودار میشود. این ابزارها قابل تنظیم هستند و زمانی که بخواهیم دادههای خود را بررسی کنیم مفید خواهند بود.
حالا روی نمایش دادههای تاخیر پرواز کار میکنیم. قبل از اینکه بتوانیم مستقیماً به نمودار برویم، باید دادهها را بارگذاری کنیم و یک بازرسی مختصر از آن انجام دهیم (خروجی کد پررنگ نشان داده شده است):
# Read the data from a csv into a dataframe
flights = pd.read_csv('../data/flights.csv', index_col=0)# Summary stats for the column of interest
flights['arr_delay'].describe()
count 327346.000000
mean 6.895377
std 44.633292
min -86.000000
25% -17.000000
50% -5.000000
75% 14.000000
max 1272.000000
خروجی ، خلاصه آمار اطلاعاتی را به ما میدهد تا تصمیمات ترسیمی خود را ایجاد کنیم: 327,346 پرواز داریم، با حداقل تاخیر 86- دقیقه (به این معنی که پرواز 86 دقیقه زودتر انجام شده است) و حداکثر تاخیر 1272 دقیقه، 21 ساعت خیره کننده است! چندک 75% فقط در 14 دقیقه است، بنابراین میتوانیم فرض کنیم که اعداد بیش از 1000 دقیقه احتمالاً پرت هستند. روی تأخیرهای بین -60 دقیقه و +120 دقیقه برای هیستوگرام خود تمرکز خواهیم کرد.
هیستوگرام یک انتخاب رایج برای مصورسازی اولیه یک متغیر است زیرا توزیع دادهها را نشان میدهد. موقعیت x مقدار متغیری است که در فواصل زمانی به نام bin گروه بندی شده است و ارتفاع هر نوار نشان دهنده تعداد نقاط داده در هر بازه است.
در کیس موردنظر ما، موقعیت x نشان دهنده تاخیر رسیدن در چند دقیقه و ارتفاع تعداد پروازها در بخش مربوطه است. Bokeh دارای Glyph هیستوگرام داخلی نیست، اما میتوانیم با استفاده از علامت چهارگانه، لبههای پایین، بالا، چپ و راست هر نوار را مشخص کنیم.
برای ایجاد دادهها برای میلهها (Bars)، از تابع Histogram در Numpy استفاده میکنیم که تعداد نقاط داده را در هر بخش مشخص شده محاسبه میکند. از بخشهای 5 دقیقهای استفاده خواهیم کرد که به این معنی است که عملکرد تعداد پروازها را در هر فاصله پنج دقیقهای تأخیر میشمارد.
هم رویش منتشر کرده است:
آموزش NumPy --- دانشمند داده شوید!
پس از تولید دادهها، آنها را در یک دیتافریم pandas قرار میدهیم تا همه دادهها در یک شی نگهداری شوند. کد زیر برای درک Bokeh مهم نیست، اما با این وجود به دلیل محبوبیت Pandas در علم داده مفید است!
"""Bins will be five minutes in width, so the number of bins
is (length of interval / 5). Limit delays to [-60, +120] minutes using the range."""arr_hist, edges = np.histogram(flights['arr_delay'],
bins = int(180/5),
range = [-60, 120])# Put the information in a dataframe
delays = pd.DataFrame({'arr_delay': arr_hist,
'left': edges[:-1],
'right': edges[1:]})
دادههای ما به این صورت است:
ستون flights شمارش تعداد پروازها در هر بازه تأخیر از left به right است. از اینجا میتوانیم یک شکل Bokeh جدید بسازیم و یک glpyh چهارتایی اضافه کنیم که پارامترهای مناسب را مشخص میکند:
# Create the blank plot
p = figure(plot_height = 600, plot_width = 600,
title = 'Histogram of Arrival Delays',
x_axis_label = 'Delay (min)]',
y_axis_label = 'Number of Flights')
# Add a quad glyph
p.quad(bottom=0, top=delays['flights'],
left=delays['left'], right=delays['right'],
fill_color='red', line_color='black')
# Show the plot
show(p)
خروجی به صورت زیر است:
بیشتر کار در تولید این نمودار در قالببندی دادهها انجام میشود که یک اتفاق معمول در علم داده است! از نمایش پلات (plot) ، میبینیم که تاخیرهای رسیدن تقریباً به طور معمول با یک انحراف مثبت جزئی یا دم بزرگ در سمت راست توزیع میشوند.
راههای سادهتری برای ایجاد یک هیستوگرام پایه در پایتون وجود دارد، و همین نتیجه را میتوان با استفاده از چند خط matplotlib انجام داد. با این حال، فایده اصلی در توسعه مورد نیاز برای پلات Bokeh در ابزارها و روشهای تعامل با دادهها است که میتوانیم به راحتی به نمودار اضافه کنیم.
افزودن تعامل
اولین نوع تعاملی که در این مجموعه به آن خواهیم پرداخت، تعاملات غیرفعال است. این موارد اقداماتی هستند که بیننده میتواند انجام دهد و دادههای نمایش دادهشده را تغییر نمیدهد. تعاملات به نوعی به عنوان بازرس هم نامیده میشوند چون به بینندگان اجازه میدهند تا دادهها را با جزئیات بیشتری “بررسی” کنند. یک بازرس مفید Tooltipیی است که وقتی کاربر روی نقاط داده قرار میگیرد ظاهر میشود و در Bokeh به نام HoverTool خوانده میشود.
برای افزودن Tooltip، باید منبع داده خود را از یک دیتافریم به یک ColumnDataSource، یک مفهوم کلیدی در Bokeh، تغییر دهیم. این مفهوم یک شی است که به طور خاص برای ترسیم استفاده میشود که شامل دادهها به همراه چندین متد و ویژگی است.
ColumnDataSource اجازه میدهد تا حاشیهنویسی و تعامل را به نمودارهای خود اضافه کنیم و میتوان آن را از طریق فریم داده Pandas ساخت. خود دادههای واقعی در dictionary قابل دسترسی از طریق ویژگی (attribute) داده ColumnDataSource نگهداری میشوند. در اینجا، منبع را از دیتافریم خود ایجاد میکنیم و به کلیدهای دیکشنری (dictionary) داده که مطابق با ستونهای دیتافریم هستند نگاه میکنیم.
# Import the ColumnDataSource class
from bokeh.models import ColumnDataSource# Convert dataframe to column data source
src = ColumnDataSource(delays)
src.data.keys()
dict_keys(['flights', 'left', 'right', 'index'])
وقتی با استفاده از ColumnDataSource عبارات را اضافه میکنیم، ColumnDataSource را به عنوان پارامتر source ارسال میکنیم و با رشتهها به نام ستونها اشاره میکنیم:
# Add a quad glyph with source this time
p.quad(source = src, bottom=0, top='flights',
left='left', right='right',
fill_color='red', line_color='black')
توجه کنید که چگونه کد به ستونهای خاص داده مانند «flights»، «left» و «right» با یک رشته به جای فرمت df[‘column’] مانند قبل اشاره میکند.
HoverTool در Bokeh
سینتکس HoverTool ممکن است در ابتدا کمی پیچیده به نظر برسد، اما با تمرین ایجاد آن بسیار آسان است. فهرستی از Tooltipها را به عنوان تاپلهای پایتونی به HoverToolinstance منتقل میکنیم که در آن عنصر اول برچسب (Label) دادهها است و عنصر دوم به دادههای خاصی اشاره میکند که میخواهیم برجسته کنیم.
میتوانیم به هر یک از ویژگیهای نمودار، مانند موقعیت x یا y با استفاده از «$» یا فیلدهای خاص در منبع خود با استفاده از «@» اشاره کنیم. احتمالاً کمی گیج کننده به نظر میرسد، در اینجا نمونهای از HoverTool است که در آن هر دو مورد را انجام میدهیم:
# Hover tool referring to our own data field using @ and
# a position on the graph using $
h = HoverTool(tooltips = [('Delay Interval Left ', '@left'), ('(x,y)', '($x, $y)')])
با استفاده از «@» به فیلد داده left در ColumnDataSource (که مربوط به ستون «left» ديتافريم اصلی است) اشاره میکنیم و با استفاده از «$» به موقعیت (x,y) مکاننما اشاره میکنیم. نتیجه به صورت زیر است:
موقعیت (x,y) موقعیت ماوس روی نمودار است و برای هیستوگرام خیلی مفید نیست، زیرا میتوانیم تعداد پروازها را در یک نوار مشخص پیدا کنیم که با بالای نوار مطابقت دارد. برای برطرف کردن این مشکل، نمونه Tooltip خود را تغییر میدهیم تا به ستون صحیح رجوع شود.
قالببندی دادههای نشان داده شده در یک Tooltip میتواند خستهکننده باشد، بنابراین ستون دیگری را با قالببندی صحیح در قالب داده ایجاد میکنیم. برای مثال، اگر میخواهیم Tooltip کل بازه زمانی یک نوار مشخص را نشان دهد، یک ستون قالببندی شده در دیتافریم (Dataframe) خود ایجاد میکنیم:
# Add a column showing the extent of each interval
delays['f_interval'] = ['%d to %d minutes' % (left, right) for left, right in zip(delays['left'], delays['right'])]
سپس این دیتافریم را به ColumnDataSource تبدیل میکنیم و در فراخوانی HoverTool خود به این ستون دسترسی پیدا میکنیم. کد زیر نمودار را با ابزار شناور با اشاره به دو ستون فرمت شده ایجاد و ابزار را به نمودار اضافه میکند:
# Create the blank plot
p = figure(plot_height = 600, plot_width = 600,
title = 'Histogram of Arrival Delays',
x_axis_label = 'Delay (min)]',
y_axis_label = 'Number of Flights')
# Add a quad glyph with source this time
p.quad(bottom=0, top='flights', left='left', right='right', source=src,
fill_color='red', line_color='black', fill_alpha = 0.75,
hover_fill_alpha = 1.0, hover_fill_color = 'navy')
# Add a hover tool referring to the formatted columns
hover = HoverTool(tooltips = [('Delay', '@f_interval'),
('Num of Flights', '@f_flights')])
# Style the plot
p = style(p)
# Add the hover tool to the graph
p.add_tools(hover)
# Show the plot
show(p)
در استایل Bokeh، عناصر را با اضافه کردن آنها به شکل اصلی در نمودار خود قرار میدهیم. توجه داشته باشید که در فراخوانی گلیف p.quad، چند پارامتر اضافی وجود دارد، hover_fill_alpha و hover_fill_color، که وقتی ماوس را روی نوار قرار میدهیم، ظاهر علامت را تغییر میدهند. همچنین با استفاده از تابع style یک استایل اضافه کردیم. نکته اصلی یک نمودار نشان دادن دادهها است و افزودن عناصر غیرضروری فقط از مفید بودن یک شکل میکاهد! طرح نهایی در زیر ارائه شده است:
همانطور که ماوس را روی نوارهای (Bars) مختلف نمودار قرار میدهیم، آمار دقیق آن نوار را دریافت میکنیم که فاصله و تعداد پروازها را در آن بازه نشان میدهد. میتوانیم آن را در یک فایل html ذخیره کنیم تا با دیگران هم به اشتراک بگذاریم:
# Import savings function
from bokeh.io import output_file# Specify the output file and save
output_file('hist.html')
show(p)
نتیجه گیری
بیشتر از یک طرح طول خواهد کشید تا بتوانید گردش کار اولیه Bokeh را درک کنید. ممکن است به نظر برسد که فراگیری Bokeh کار زیادی دارد، اما مزایای آن زمانی به دست میآید که بخواهید تصاویر خود را فراتر از شکلهای ثابت ساده گسترش دهید.
هنگامی که یک نمودار اساسی داشته باشید، میتوانید با افزودن عناصر بیشتر، اثربخشی تصویر را افزایش دهید. به عنوان مثال، اگر بخواهیم به تاخیر ورود توسط خطوط هوایی نگاه کنیم، میتوانیم یک نمودار تعاملی ایجاد کنیم که به کاربران این امکان را میدهد خطوط هوایی را انتخاب و مقایسه کنند. در تصویر زیر دید خوبی به آنچه میتوانیم انجام دهیم وجود دارد:
تعاملات فعال نیازمند اسکریپت نویسی بیشتر است، اما این فرصت را میدهد تا روی پایتون خود کار کنیم!
تاکید میکنیم که Bokeh یا هر ابزار کتابخانهای دیگر هرگز یک ابزار یکپارچه برای تمام نیازهای رسم پلات شما نخواهد بود. Bokeh برای امکان کاوش نمودارها به کاربران عالی است، اما برای کاربردهای دیگر، مانند تجزیه و تحلیل دادههای اکتشافی ساده، یک کتابخانه سبک وزن مانند matplotlib کارآمدتر خواهد بود. هرچه کتابخانههای بیشتری بشناسید، برای استفاده از ابزار مصورسازی مناسب برای کارتان، مجهزتر خواهید بود.
کلیدواژگان
مصورسازی داده با Bokeh | مصورسازی داده ها با Bokeh | تعاملیسازی نمودار با Bokeh | مصورسازی داده با bokeh | مصورسازی داده ها | data visualization چیست | مصورسازی داده با پایتون | مصورسازی تعاملی دادهها | مصورسازی داده | مصورسازی تعاملی داده | data visualization چیست | تعاملیسازی نمودار با Bokeh | پایتون مصورسازی داده
منبع
data-visualization-with-bokeh-in-python