مصورسازی داده، تجسمسازی داده یا Data Visualization ارائهی گرافیکی داده است که هدف اصلی آن انتقال بهینهی اطلاعات به کاربران از طریق نمایش روابط میان دادهها به کمک نمودارها است. Matplotlib از کتابخانههای معروف پایتون برای ترسیم نمودارهاست. Seaborn از دیگر کتابخانههای پایتون برای مصورسازی است که بر پایهی Matplotlib بنا شده و امکانات بیشتری برای کاربران در جهت ترسیم نمودارها فراهم میکند. هر دوی این کتابخانهها جزو کتابخانههای بسیار پرکاربرد رسم نمودار و مصور سازی داده در پایتون هستند. از آنجایی که یادگیری پکیجهای Numpy، Pandas، Matplotlib و Seaborn برای شروع یادگیری دادهکاوی با پایتون بسیار ضروری است در این مقاله ضمن معرفی انواع نمودارهای پرکاربرد در مصورسازی دادهها به آموزش Matplotlib و در ادامهی آن به آموزش Seaborn میپردازیم.
Matplotlib از کتابخانههای رسم نمودار در زبان برنامهنویسی پایتون است که به همراه بسیاری از کتابخانههای این زبان که بر مبنای کار با مقادیر عددی مانند NumPy و Pandas توسعه یافته اند به کار گرفته میشود.
Matplotlib برای گنجاندن نمودارها در اپلیکیشنها با استفاده از ابزارهای گرافیکی پایتون مانند Tkinter، wxPyton و … API مبتنی بر شی گرایی فراهم میکند. Matplotlib توسط JohnD.Hunter در سال 2003 توسعه داده شد. برای اطلاعات بیشتر به وبسایت آن مراجعه کنید.
matplotlib.pyplot مجموعهای از دستورات و توابعی است که کتابخانهی matplotlib را قادر میسازد تا همانند زبان برنامهنویسی MATLAB باشد. هر تابع pyplot میتواند تغییراتی در شکل نمودار مانند رسم نمودار، ایجاد خطوطی در ناحیهی ترسیم شده، ایجاد برچسب برای نمودار و … ایجاد کند. در matplotlib.pyplot حالتهای مختلف حین فراخوانی توابع حفظ میشود، به طوری که تأثیر مواردی همچون شکل فعلی و ناحیهی رسم شده حفظ میشود و موارد جدید از تغییرات ناشی از فراخوانی توابع بر روی محورهای فعلی اعمال میشود.
Matplotlib موارد استفاده و فرمتهای خروجی مختلفی را شامل میشود. برخی افراد با استفاده از python shell را برای تعامل با matplotlib استفاده میکنند و شکل نمودار مانند پنجرههای pop up برای آنها ظاهر میشود (مانند دیدن تصاویر نمودار در MATLAB )
برخی هم از JupyterNotebook برای نوشتن کدهای خود استفاده میکنند و نمودارهای حاصل را به طور inline در همان صفحه زیر کدهای خود میبینند که این روش باعث تجزیه تحلیل سریعتر و آسانتر کدها و نتایج آنها است. برخی هم mathplotlib را به صورت اسکریپتهایی برای تولید تصاویر postscript از شبیهسازیهای عددی استفاده میکنند.
برای پشتیبانی تمامی این موارد استفاده mathplotlib قادر است انواع مختلف خروجی را تولید کند و همهی این موارد در پس زمینه یا backend این کتابخانه گنجانده شده است.
matplotlib جزء آن دسته از پکیجهایی است که امکانات گرافیکی زیادی برای مصورسازی دادهها همچون ترسیمات دوبعدی، سه بعدی و حتی انیمیشن را فراهم میکند. در این مقاله به نحوهی رسم نمودار دوبعدی در پایتون میپردازیم. در میان نمودارهای دوبعدی ترسیم خطوط، نمودار پراکندگی، میلهای، هیستوگرام، دایرهای و سایر نمودارهای پرکاربرد را بررسی میکنیم.
برای رسم یک خط در کتابخانهی مت پلات مراحل زیر را داریم:
# importing the required module
import matplotlib.pyplot as plt
# x axis values
x = [1,2,3]
# corresponding y axis values
y = [2,4,1]
# plotting the points
plt.plot(x, y)
# naming the x axis
plt.xlabel('x - axis')
# naming the y axis
plt.ylabel('y - axis')
# giving a title to my graph
plt.title('My first graph!')
# function to show the plot
plt.show()
برای رسم دو یا چند خط بر روی یک نمودار مانند کد زیر عمل میکنیم که در آن:
import matplotlib.pyplot as plt
# line 1 points
x1 = [1,2,3]
y1 = [2,4,1]
# plotting the line 1 points
plt.plot(x1, y1, label = "line 1")
# line 2 points
x2 = [1,2,3]
y2 = [4,1,3]
# plotting the line 2 points
plt.plot(x2, y2, label = "line 2")
# naming the x axis
plt.xlabel('x - axis')
# naming the y axis
plt.ylabel('y - axis')
# giving a title to my graph
plt.title('Two lines on same graph!')
# show a legend on the plot
plt.legend()
# function to show the plot
plt.show()
در رسم نمودارها به کمک مت پلات میتوان ویژگیهای بیشتری را به نمودار افزود.
نمودار حاصل از کد مثال زیر را در نظر بگیرید:
import matplotlib.pyplot as plt
# x axis values
x = [1,2,3,4,5,6]
# corresponding y axis values
y = [2,4,1,5,2,6]
# plotting the points
plt.plot(x, y, color='green', linestyle='dashed', linewidth = 3,
marker='o', markerfacecolor='blue', markersize=12)
# setting x and y axis range
plt.ylim(1,8)
plt.xlim(1,8)
# naming the x axis
plt.xlabel('x - axis')
# naming the y axis
plt.ylabel('y - axis')
# giving a title to my graph
plt.title('Some cool customizations!')
# function to show the plot
plt.show()
همانطور که در شکل میبینید در این نمودار:
نمودار میلهای یا نواری (Bar Plot) نموداری است که دادههای طبقه بندی شده را با میلههای مستطیل شکل با ارتفاع یا طول متناسب با مقادیر ارائه شده نشان میدهد. میلهها میتوانند به شکل عمودی یا افقی رسم شوند که گاهی نمودار میلهای عمودی، نمودار خطی نامیده میشود.
در شکل زیر یک نمودار میلهای را به صورت عمودی میبینیم:
import matplotlib.pyplot as plt
# x-coordinates of left sides of bars
left = [1, 2, 3, 4, 5]
# heights of bars
height = [10, 20, 30, 40, 50]
# labels for bars
tick_label = ['one', 'two', 'three', 'four', 'five']
# plotting a bar chart
plt.bar(left, height, tick_label = tick_label,
width = 0.8, color = ['blue', 'green', 'red','yellow','black'])
# naming the x-axis
plt.xlabel('x - axis')
# naming the y-axis
plt.ylabel('y - axis')
# plot title
plt.title('bar chart!')
# function to show the plot
plt.show()
در این نمودار:
نمودار هیستوگرام یک نمایش دقیق از توزیع دادههای عددی است. این نمودار تخمینی از توزیع احتمال متغیر پیوسته است و برای اولین بار توسط کارل پیرسون معرفی شده است. تفاوت نمودار هیستوگرام با نمودار میلهای در این است که یک نمودار میلهای رابطهی دو متغیر را با هم نشان میدهد. اما هیستوگرام تنها به یک متغیر مربوط میشود.
import matplotlib.pyplot as plt
# frequencies
ages = [2,5,70,40,30,45,50,45,43,40,44,
60,7,13,57,18,90,77,32,21,20,40]
# setting the ranges and no. of intervals
range = (0, 100)
bins = 5
# plotting a histogram
plt.hist(ages, bins, range, color ='red',
histtype = 'bar', rwidth = 0.8)
# x-axis label
plt.xlabel('age')
# frequency label
plt.ylabel('No. of people')
# plot title
plt.title('My histogram')
# function to show the plot
plt.show()
در این نمودار:
نمودار پراکندگی یا Scatter Plot نوعی از نمودار است که با استفاده از مختصات دکارتی مقادیر دو متغیر را برای مجموعهای از اعداد نمایش میدهد. در قطعه کد زیر رسم نمودار نقطهای در پایتون یا همان نمودار پراکندگی را با هم میبینیم:
import matplotlib.pyplot as plt
# x-axis values
x = [1,2,3,4,5,6,7,8,9,10]
# y-axis values
y = [2,4,5,7,6,8,9,11,12,12]
# plotting points as a scatter plot
plt.scatter(x, y, label= "stars", color= "green",
marker= "*", s=30)
# x-axis label
plt.xlabel('x - axis')
# frequency label
plt.ylabel('y - axis')
# plot title
plt.title('My scatter plot!')
# showing legend
plt.legend()
# function to show the plot
plt.show()
در این نمودار:
نمودار دایرهای یا Pie-Chart یک شکل آماری دایرهای است که برای نشان دادن نسبت و سهم عددی به برشهایی متناظر با هر کدام از آن نسبتها تقسیم میشود. در نمودار دایرهای طول قوس هر برش متناسب با کمیتی است که نشان میدهد.
import matplotlib.pyplot as plt
# defining labels
activities = ['eat', 'sleep', 'work', 'play']
# portion covered by each label
slices = [3, 7, 8, 6]
# color for each label
colors = ['r', 'y', 'g', 'b']
# plotting the pie chart
plt.pie(slices, labels = activities, colors=colors,
startangle=90, shadow = True, explode = (0, 0, 0.1, 0),
radius = 1.2, autopct = '%1.1f%%')
# plotting legend
plt.legend()
# showing the plot
plt.show()
در این نمودار:
میتوان منحنی معادلات و چند جملهای با درجههای مختلف را ترسیم نمود. برای مثال رسم نمودار سینوسی در پایتون یا همان y=sin(x) که x برحسب رادیان است، مانند کد زیر است:
# importing the required modules
import matplotlib.pyplot as plt
import numpy as np
# setting the x - coordinates
x = np.arange(0, 2*(np.pi), 0.1)
# setting the corresponding y - coordinates
y = np.sin(x)
# potting the points
plt.plot(x, y)
# function to show the plot
plt.show()
خروجی قطعه کد بالا به شکل زیر است:
در اینجا از NumPy که یک کتابخانهی عمومی برای کار با اعداد است استفاده کردهایم.
مثالهایی از توابع دیگر همچون رسم نمودار لگاریتمی در پایتون را میتوان مانند قطعه کد بالا به کمک matplotlib رسم کرد (y=np.log(x)).
زمانی که میخواهیم دو یا چند نمودار را در یک شکل نمایش دهیم از subplot استفاده میکنیم. این کار را با استفاده از دو روش مختلف میتوان انجام داد:
روش اول رسم زیر نمودار یا Subplot:
# importing required modules
import matplotlib.pyplot as plt
import numpy as np
# function to generate coordinates
def create_plot(ptype):
# setting the x-axis vaues
x = np.arange(-10, 10, 0.01)
# setting the y-axis values
if ptype == 'linear':
y = x
elif ptype == 'quadratic':
y = x**2
elif ptype == 'cubic':
y = x**3
elif ptype == 'quartic':
y = x**4
return(x, y)
# setting a style to use
plt.style.use('fivethirtyeight')
# create a figure
fig = plt.figure()
# define subplots and their positions in figure
plt1 = fig.add_subplot(221)
plt2 = fig.add_subplot(222)
plt3 = fig.add_subplot(223)
plt4 = fig.add_subplot(224)
# plotting points on each subplot
x, y = create_plot('linear')
plt1.plot(x, y, color ='r')
plt1.set_title('$y_1 = x$')
x, y = create_plot('quadratic')
plt2.plot(x, y, color ='b')
plt2.set_title('$y_2 = x^2$')
x, y = create_plot('cubic')
plt3.plot(x, y, color ='g')
plt3.set_title('$y_3 = x^3$')
x, y = create_plot('quartic')
plt4.plot(x, y, color ='k')
plt4.set_title('$y_4 = x^4$')
# adjusting space between subplots
fig.subplots_adjust(hspace=.5,wspace=0.5)
# function to show the plot
plt.show()
کد بالا را مرحله به مرحله بررسی میکنیم:
:plt.style.use(‘fivethirtyeight’)
شکل نمودارها با تنظیم استایلهای مختلف موجود یا دلخواه خود میتوانند تنظیم شوند.
این ویژگی به عنوان یک ظرف سطح بالا برای تمامی عناصر نمودار عمل میکند. بنابراین ما یک شکلی تحت عنوان fig تعریف میکنیم که همهی عناصر زیرنمودارها را در بر بگیرد.
add_subplot(nrows, ncols, plot_number)
plt2 = fig.add_subplot(222)
plt3 = fig.add_subplot(223)
plt4 = fig.add_subplot(224)
اگر یک زیر نمودار در شکلی وجود داشته باشد، می توان شکل را در وضعیتی تصور کرد که به سطرها و ستونهایی تقسیم شده است. (یعنی nrows برای سطرها و ncols برای ستونها) پارامتر plot_number بیانگر زیرنموداری است که تابع آن را فراخوانی میکند تا آن زیرنمودار را رسم کند. Plot_number میتواند محدودهای از عدد یک تا ماکسیمم میان مقادیر nrows و ncols را داشته باشد. اگر مقادیر این سه پارامتر کمتر از 10 باشند، تابع subplot میتواند تنها با یک مقدار پارامتر عددی صحیح فراخوانی شود که رقم هزارگان این عدد بیانگر تعداد سطرها یا همان nrows ، رقم دهگان نشاندهندهی تعداد ستونها یا همان ncols و رقم یکان بیانگر مقدار پارامتر plot_number است. این به این معنی است که به جای subplot(2,3,4) میتوان نوشت subplot(234) .
x, y = create_plot(‘linear’)
plt1.plot(x, y, color =’r’)
plt1.set_title(‘$y_1 = x$’)
میخواهیم نقاط هر زیرنمودار را رسم کنیم. ابتدا محورهای x و y را با تابع create_plot و تعیین نوع بردار مورد نظر، ایجاد میکنیم. سپس نقاط روی زیرنمودار را با متد .plot رسم میکنیم. عنوان subplot را هم با متد set_title ایجاد میکنیم. با استفاده از $ در آغاز و پایان عنوان مورد نظرمان این اطمینان را حاصل میکنیم که در متن عنوان نمودار علامت underscore یا “_” به شکل اندیس یا همان subscript و علامت “^” برای توان یا همان superscript خوانده میشوند.
fig.subplots_adjust(hspace=.5,wspace=0.5)
این متد برای ایجاد فاصله میان زیرنمودارها به کارگرفته میشود.
روش دوم رسم زیر نمودار یا Subplot:
# importing required modules
import matplotlib.pyplot as plt
import numpy as np
# function to generate coordinates
def create_plot(ptype):
# setting the x-axis vaues
x = np.arange(0, 5, 0.01)
# setting y-axis values
if ptype == 'sin':
# a sine wave
y = np.sin(2*np.pi*x)
elif ptype == 'exp':
# negative exponential function
y = np.exp(-x)
elif ptype == 'hybrid':
# a damped sine wave
y = (np.sin(2*np.pi*x))*(np.exp(-x))
return(x, y)
# setting a style to use
plt.style.use('ggplot')
# defining subplots and their positions
plt1 = plt.subplot2grid((11,1), (0,0), rowspan = 3, colspan = 1)
plt2 = plt.subplot2grid((11,1), (4,0), rowspan = 3, colspan = 1)
plt3 = plt.subplot2grid((11,1), (8,0), rowspan = 3, colspan = 1)
# plotting points on each subplot
x, y = create_plot('sin')
plt1.plot(x, y, label = 'sine wave', color ='b')
x, y = create_plot('exp')
plt2.plot(x, y, label = 'negative exponential', color = 'r')
x, y = create_plot('hybrid')
plt3.plot(x, y, label = 'damped sine wave', color = 'g')
# show legends of each subplot
plt1.legend()
plt2.legend()
plt3.legend()
# function to show plot
plt.show()
بیایید به بررسی قسمتهای مهم این کد بپردازیم:
plt1 = plt.subplot2grid((11,1), (0,0), rowspan = 3, colspan = 1)
plt2 = plt.subplot2grid((11,1), (4,0), rowspan = 3, colspan = 1)
plt3 = plt.subplot2grid((11,1), (8,0), rowspan = 3, colspan = 1)
Subplot2grid مشابه pyplot.subplot است اما از اندیسگذاری مبتنی بر صفر استفاده میکند و این امکان را فراهم میکند که زیرنمودار چندین خانه را اشغال کند. توضیح آرگومانهای این متد به شرح زیر است:
در مثال ما هر زیرنمودار سه سطر و یک ستون را با دو سطر خالی (سطرهای شمارهی 4 و 8 ) پوشش میدهد.
توجه: پس از بررسی دو مثال بالا متوجه شدیم که از متد subplot زمانی استفاده میکنیم که اندازهی نمودارها یکسان باشد و این در حالی است که متد subplot2grid انعطاف بیشتری بر روی مکان و اندازهی زیرنمودارها در اختیار ما قرار میدهد.
Matpliotlib در ابتدا برای ترسیمات دو بعدی طراحی شده بود. پس از مدتی برخی از ابزارهای ترسیم سه بعدی برمبنای ترسیمات دو بعد این کتابخانه ترسیم شد و نتیجهی آن مجموعهای مناسب (اگرچه کمی محدود ) از ابزارها برای ترسیمات سه بعدی است. امکان ترسیمات سه بعدی با ابزار toolkit و matplotlib فراهم میشود.
from mpl_toolkits import mplot3d
پس از وارد کردن ماژول mplot3d به کمک کلمهی کلیدی projection=’3d’ میتوان محورهای سه بعدی را کنار توابع معمول رسم محورها، ترسیم نمود. به کد زیر و خروجی آن توجه کنید:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.axes(projection='3d')
خروجی نمودار به شکل زیر است:
پایهایترین نمودار سه بعدی خط یا مجموعهای از نقاط پراکنده است که با سه تایی (x,y,z) ایجاد میشود. این کار را با توابع ax.plot3D و ax.scatter3D انجام میدهیم. با کد زیر یک مارپیچ مثلثاتی (spiral) را به نقاطی که به طور تصادفی اطراف خط آن هستند، رسم میکنیم.
ax = plt.axes(projection='3d')
# Data for a three-dimensional line
zline = np.linspace(0, 15, 1000)
xline = np.sin(zline)
yline = np.cos(zline)
ax.plot3D(xline, yline, zline, 'gray')
# Data for three-dimensional scattered points
zdata = 15 * np.random.random(100)
xdata = np.sin(zdata) + 0.1 * np.random.randn(100)
ydata = np.cos(zdata) + 0.1 * np.random.randn(100)
ax.scatter3D(xdata, ydata, zdata, c=zdata, cmap='Greens');
خروجی به شکل زیر است:
در مثال زیر یک نمودار کانتور سه بعدی از یک تابع سینوسی سه بعدی را نشان خواهیم داد.
def f(x, y):
return np.sin(np.sqrt(x ** 2 + y ** 2))
x = np.linspace(-6, 6, 30)
y = np.linspace(-6, 6, 30)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig = plt.figure() ax = plt.axes(projection='3d') ax.contour3D(X, Y, Z, 50, cmap='binary') ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z');
خروجی، نموداری به شکل زیر است:
گاهی زاویهی دید نمودار مناسب نیست. میتوان با کمک تابع view_init زوایای ارتفاع و آزیموت نمودار را تنظیم کرد. در مثال زیر از ارتفاع 60 درجه (یعنی 60 درجه بالای صفحهی x-y) و یک آزیموت 35 درجه (یعنی 35 درجه خلاف جهت عقربههای ساعت در مورد محور z میچرخیم) استفاده خواهیم کرد:
ax.view_init(60, 35)
fig
خروجی کد، نموداری به شکل زیر است:
دو نوع دیگر از اشکال سه بعدی که با دادههای شبکهای (grid) سر و کار دارند، قاب سیمی (wire frame) و پوسته (surface) نام دارند. این نمودارها شبکهی دادهها را به شکل پوستهای سه بعدی نمایش میدهند. در کد زیر مثالی از این نوع دادهها و ترسیمات را میبینیم:
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot_wireframe(X, Y, Z, color='black')
ax.set_title('wireframe');
خروجی کد، به شکل زیر است:
طرح پوسته نیز مانند قاب سیمی است با این تفاوت که هر وجه آن با یک چند ضلعی پر شده است. افزودن یک طرح زنگی به هر وجه میتواند به تجسم و درک بهتر توپولوژی پوسته کمک کند.
ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap='viridis', edgecolor='none')
ax.set_title('surface');
خروجی کد به شکل زیر است:
Seaborn کتابخانهای برای ایجاد گرافیکهای آماری در پایتون است. این کتابخانه بر مبنای matplotlib ساخته شده و با ساختار داده در Pandas ادغام شده است. برخی از کاربردهای seaborn عبارتند از:
هدف seaborn این است که تجسمسازی را به بخش اصلی کاوش و درک داده تبدیل کند. توابع نموداری مبتنی بر مجموعهی داده بر روی دیتافریمها و آرایههای حاوی مجموعهی دادهها کار میکنند و به صورت داخلی نگاشت معنایی مورد نیاز و جمعآوری آماری را برای تولید نمودارهای دارای بار اطلاعاتی مفید انجام میدهد. برای اطلاعات بیشتر میتوانید به این سایت مراجعه کنید.
در این قسمت این دو کتابخانه را با هم از نظر چند معیار بررسی میکنیم:
Matplotlib: matplotlib به طور عمده برای ترسیمات پایهای گسترش یافته است. مجسمسازی داده به طور عمده شامل نمودار میلهای، دایرهای، خطی، نمودارهای نقطهای یا پراکنده و غیره میباشد.
Seaborn: seaborn از طرف دیگر الگوهای مختلفی از تجسمسازی را ارائه می دهد. این کتابخانه از قواعد دستوری کمتری استفاده میکند و تمهای از پیش تعریف شدهی جالبی دارد.
در تجسمسازی آماری بسیار متخصص است و در تجسمسازی دادههای خلاصه و توزیع آماری دادهها به کار میرود.
Matplotlib: matplotlib فیگورهای چندگانه را میتواند باز کند اما باید به طور صریح بسته شوند. تابع plt.close تنها فیگور فعلی را میبندد و plt.close(‘all’) تمامی شکلها را میبندد.
Seaborn: seaborn ایجاد اشکال چندگانه را به طور اتوماتیک ممکن میسازد ولی گاهی مشکلات ظرفیت حافظه ممکن است ایجاد شود.
Matplotlib یک پکیج گرافیکی برای تجسمسازی داده در پایتون است. به خوبی با NumPy و Pandas تجمیع شده است. ماژول pyplot دستورات ترسیم MATLAB را منعکس میکند. از این رو کاربران متلب به راحتی در پایتون میتوانند ترسیم داده بکنند.
Seaborn بیشتر با دیتافریمهای پانداس تجمیع شده است. کتابخانه های matplotlib را برای ایجاد گرافیکهای زیبا در پایتون با استفاده از متدهایی گسترش میدهد.
Matplotlib با دیتافریمها و آرایهها کار میکند. APIهای متفاوتی برای ترسیم دارد. شکلها توسط آبجکت هایی نمایش داده میشوند و تابع plot مشابه فراخوانیهای بدون پارامتر است و نیاز به مدیریت پارامتر نیست.
Seaborn با مجموعه داده کار می کند و نسبت به matplotlib بسیار بصریتر است.
در seaborn تابع replot برای مشخص کردن نوع نمودار ترسیمی مقدار پارامتر kind را مقداردهی میکند که مقدار این پارامتر میتواند بیانگر نوع خط، نمودار میلهای، هیستوگرام و… یا هر نوع دیگری از نمودارها باشد.
Seaborn برخلاف matplotlib حالتمند یا statefull نیست. از این رو تابع plot در آن نیاز به ارسال آبجکت دارد.
Matplotlib بسیار قابل تنظیم و قدرتمند است.
Seaborn تمهای از پیش آماده شدهی زیادی برای استفاده دارد.
Pandas از matplotlib استفاده می کند. Seaborn برای موارد مورد استفادهی خاصتری به کار میرود. تحت matplotlib است و بیشتر برای نمایش موارد آماری به کار میرود.
کتابخانهی pandas را که قابلیت بالایی در کنترل مجموعه دادههای رابطهای دارد وارد میکنیم سپس matplotlib را هم که ما را در افزودن ویژگیهای مد نظرمان به نمودارها کمک میکند وارد میکنیم. سپس کتابخانهی seaborn را import میکنیم. اکنون مجموعه دادهی مورد نظر را به شکل زیر وارد میکنیم:
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
از مجموعه دادهی Pokemon استفاده میکنیم. این مجموعه داده را که به فرمت فایل csv است با کمک pandas به شکل دستور زیر میخوانیم:
# Read dataset
df = pd.read_csv('Pokemon.csv', index_col=0)
آرگومان index_col=0 به این معنی است که ستون اول مجموعه داده را به عنوان ستون شناسه یا همان ID در نظر میگیریم. پنج سطر اول مجموعه داده به شکل زیر است:
همان طور که میبینید این دیتاست اطلاعات مربوط به آمار 151 مورد Pokemon را دارد.
یکی از بزرگترین نقاط قوت seaborn تنوع و راحتی استفادهی توابع موجود برای رسم نمودارها است. به طور مثال ایجاد نمودار پراکندگی (scatter plot) تنها با یک خط کد lmplot() است.
دو روش کلی که شما میتوانید انجام دهید:
به طور مثال در قطعه کد زیر ستونهای Attack و Defense به دو روش بیان شدهاند:
# Recommended way
sns.lmplot(x='Attack', y='Defense', data=df)
# Alternative way
# sns.lmplot(x=df.Attack, y=df.Defense)
به هر حال seaborn تابعی برای رسم نمودار پراکندگی به طور اختصاصی ندارد از این رو در شکل یک خط مورب را مشاهده میکنید. (ما در واقع از تابع seaborn برای رسم رگرسیون خطی استفاده کردهایم.)
خوشبختانه هر تابع رسم چندین گزینهی مفید دارد که میتوان بنا به نیاز آنها را مقداردهی کرد. نحوهی مقداردهی پارامترهای lmplot() به شکل زیر است:
# Scatterplot arguments
sns.lmplot(x='Attack', y='Defense', data=df,
fit_reg=False, # No regression line
hue='Stage') # Color by evolution stage
همانطور که قبلاً گفتیم seaborn بر روی matplotlib طراحی شده است و با اینکه امکانات بیشتری نسبت به matplotlib در اختیار ما قرار میدهد اما با این وجود گاهی به آن نیاز داریم. برای تنظیم محدودهی محورها مراحل زیر را انجام دهید:
# Plot using Seaborn
sns.lmplot(x='Attack', y='Defense', data=df,
fit_reg=False,
hue='Stage')
# Tweak using Matplotlib
plt.ylim(0, None)
plt.xlim(0, None)
برای اطلاعات بیشتر در مورد توابع سفارشیسازی matplotlib به داکیومنت آن مراجعه کنید.
اگرچه در این مقاله به آموزش seaborn میپردازیم همانطور که پیش از این گفتیم pandas نقش مهمی دارد. توابع رسم نمودار seaborn از مفهوم ساختار دادهی دیتافریم بسیار بهره میبرد. برای مثال در ادامه نحوهی ایجاد نمودار جعبهای را برای مجموعه دادهمان بررسی میکنیم.
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
# Boxplot
sns.boxplot(data=df)
در این نمودار میتوانیم ستون Total را حذف کنیم چون بقیه از هم مستقلاند، میتوانیم Stage و Legendary را حذف کنیم چون تاثیری در آمار ندارند. به نظر میرسد که انجام این کار تنها به کمک seaborn کار سادهای نیست. در عوض دیتافریم این کار را بسیار ساده میکند. بیایید دیتافریم جدیدی تحت عنوان stats_df که تنها ستونهای آماری را نگه میدارد به شکل زیر تعریف کنیم.
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
# Pre-format DataFrame
stats_df = df.drop(['Total', 'Stage', 'Legendary'], axis=1)
# New boxplot using stats_df
sns.boxplot(data=stats_df)
همانطور که در شکل میبینید به راحتی ستونهای مورد نیاز را به کمک قواعد Pandas استخراج کردیم.
مزیت دیگر seaborn وجود تمهای شکلدهی مناسبی است که در آن گنجانده شدهاند. تم پیشفرض “darkgrid” نام دارد. میتوانیم این تم را حین ایجاد violin plot به ‘whitegrid’ تغییر دهیم.
برای مثال میتوانیم توزیع ستون Attack به شکل زیر نمایش دهیم:
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
# Set theme
sns.set_style('whitegrid')
# Violin plot
sns.violinplot(x='Type 1', y='Attack', data=df)
همانطور که میبینید انواع Dragon تمایل دارند که آمار حملات بیشتری نسبت به انواع Ghost داشته باشند اما پراکندگی بزرگتری نیز دارند.
حالا طرفداران بازی Pokemon چیزهای جالبی راجب این نمودار ببینند: رنگهای به کار گرفته شده بدون مفهوم خاصی نیستند. چرا باید نوع Grass به رنگ صورتی یا دادهی Water به رنگ نارنجی باشد. بهتر است این را برطرف کنیم.
خوشبختانه seaborn امکان تنظیم پالت رنگی دلخواه را به ما میدهد. میتوانیم لیستی از مقادیر کدهای هگزای رنگ را به سادگی ایجاد کنیم. در زیر لیستی از این رنگها را با هم میبینیم:
pkmn_type_colors = ['#78C850', # Grass
'#F08030', # Fire
'#6890F0', # Water
'#A8B820', # Bug
'#A8A878', # Normal
'#A040A0', # Poison
'#F8D030', # Electric
'#E0C068', # Ground
'#EE99AC', # Fairy
'#C03028', # Fighting
'#F85888', # Psychic
'#B8A038', # Rock
'#705898', # Ghost
'#98D8D8', # Ice
'#7038F8', # Dragon
]
به سادگی میتوان با کمک آرگومان palette مقدار رنگها را دوباره برای نمودار خود تنظیم کنیم.
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
pkmn_type_colors = ['#78C850', # Grass
'#F08030', # Fire
'#6890F0', # Water
'#A8B820', # Bug
'#A8A878', # Normal
'#A040A0', # Poison
'#F8D030', # Electric
'#E0C068', # Ground
'#EE99AC', # Fairy
'#C03028', # Fighting
'#F85888', # Psychic
'#B8A038', # Rock
'#705898', # Ghost
'#98D8D8', # Ice
'#7038F8', # Dragon
]
2
3
# Violin plot with Pokemon color palette
sns.violinplot(x='Type 1', y='Attack', data=df,
palette=pkmn_type_colors) # Set color palette
نمودارهای ویولن برای مصورسازی نحوهی توزیع در آمار بسیار عالی هستند. به هر حال از آنجاییکه در مجموعه دادهی Pokemon تنها صد و پنجاه و یک نمونه داریم میتوانیم به راحتی هر نمونه را نمایش دهیم. برای همین از نمودار پراکندگی (swarm plot) استفاده میکنیم.
شکل نهایی هر نمونه را به شکل نقطهای مجزا با همان مقادیر در نمودار ویولن نشان میدهد.
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
pkmn_type_colors = ['#78C850', # Grass
'#F08030', # Fire
'#6890F0', # Water
'#A8B820', # Bug
'#A8A878', # Normal
'#A040A0', # Poison
'#F8D030', # Electric
'#E0C068', # Ground
'#EE99AC', # Fairy
'#C03028', # Fighting
'#F85888', # Psychic
'#B8A038', # Rock
'#705898', # Ghost
'#98D8D8', # Ice
'#7038F8', # Dragon
]
# Swarm plot with Pokemon color palette
sns.swarmplot(x='Type 1', y='Attack', data=df,
palette=pkmn_type_colors)
حال سوال این است که آیا میتوان نمودار swarm و ویولن را از آنجایی که اطلاعات مشابهی را نمایش میدهند، با هم ترکیب کرد؟
پاسخ مثبت است. پوشاندن نمودارها با یکدیگر به کمک seaborn ساده و مشابه matplotlib است. کاری که میبایست انجام دهیم به شرح زیر است:
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
pkmn_type_colors = ['#78C850', # Grass
'#F08030', # Fire
'#6890F0', # Water
'#A8B820', # Bug
'#A8A878', # Normal
'#A040A0', # Poison
'#F8D030', # Electric
'#E0C068', # Ground
'#EE99AC', # Fairy
'#C03028', # Fighting
'#F85888', # Psychic
'#B8A038', # Rock
'#705898', # Ghost
'#98D8D8', # Ice
'#7038F8', # Dragon
]
# Set figure size with matplotlib
plt.figure(figsize=(10,6))
# Create plot
sns.violinplot(x='Type 1',
y='Attack',
data=df,
inner=None, # Remove the bars inside the violins
palette=pkmn_type_colors)
sns.swarmplot(x='Type 1',
y='Attack',
data=df,
color='k', # Make points black
alpha=0.7) # and slightly transparent
# Set title with matplotlib
plt.title('Attack by Type')
همانطور که در شکل میبینید نمودار جالبی داریم که چگونگی توزیع حملات را میان انواع مختلف pokemon نشان میدهد.
اما اگر بخواهیم سایر اطلاعات آماری را ببینیم بایستی چه کنیم؟
میتوانیم نمودار فوق را برای سایر موارد آماری تکرار کنیم. اما راه دیگری وجود دارد که به کمک آن تمامی موارد را در یک نمودار نمایش دهیم.
تنها نیاز است که آمادهسازی داده را به کمک pandas انجام دهیم. ابتدا شکل و نحوهی دادهها در جدول مربوطه را یادآوری میکنیم.
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
stats_df.head()
همانطور که میبینید تمامی آمارها در ستونهای مجزا هستند. فرض کنید میخواهیم همهی آنها را در یک ستون ترکیب کنیم. به این منظور از تابع melt() پانداس استفاده میکنیم که سه پارامتر دارد.
خروجی به شکل زیر است:
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
# Melt DataFrame
melted_df = pd.melt(stats_df,
id_vars=["Name", "Type 1", "Type 2"], # Variables to keep
var_name="Stat") # Name of melted variable
melted_df.head()
تمامی شش ستون آماری در یک ستون ترکیب شدهاند و ستون آماری جدید بیانگر مقادیر اصلی است. در حقیقت اگر ابعاد این دو دیتافریم را مقایسه کنیم به نتیجهی زیر میرسیم:
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
# Melt DataFrame
melted_df = pd.melt(stats_df,
id_vars=["Name", "Type 1", "Type 2"], # Variables to keep
var_name="Stat") # Name of melted variable
print( stats_df.shape )
print( melted_df.shape )
ابعاد داده به شکل زیر است:
(151, 9) (906, 5)
در اصل نکته اینجاست که melted_df شش مرتبه سطرهای stats_df را تکرار کرده است. میتوانیم نمودار پراکندگی با melted_df را رسم کنیم. اما این دفعه:
# Swarmplot with melted_df
sns.swarmplot(x='Stat', y='value', data=melted_df,
hue='Type 1')
برای اینکه نمودار بالا خواناتر و بهتر شود میتوان ترفندهای زیر را به کار برد:
# 1. Enlarge the plot
plt.figure(figsize=(10,6))
sns.swarmplot(x='Stat',
y='value',
data=melted_df,
hue='Type 1',
split=True, # 2. Separate points by hue
palette=pkmn_type_colors) # 3. Use Pokemon palette
# 4. Adjust the y-axis
plt.ylim(0, 260)
# 5. Place legend to the right
plt.legend(bbox_to_anchor=(1, 1), loc=2)
نمودار هیستوگرام توزیع متغیرهای عددی را نمایش میدهد.
# Pandas for managing datasets
import pandas as pd
# Matplotlib for additional customization
from matplotlib import pyplot as plt
# Seaborn for plotting and styling
import seaborn as sns
# Read dataset
df = pd.read_csv("C:/Users/Naghsh/Downloads/Pokemon.csv",encoding = "ISO-8859-1", index_col=0, )
#------------------------------------------------------------------------------------
# Distribution Plot (a.k.a. Histogram)
sns.distplot(df.Attack)
نمودار هیستوگرام برای نمایش چگونگی توزیع ستون Attack به شکل زیر است:
نمودار میلهای برای توزیع متغیرهای با مقادیر طبقه بندی شده مفید است.
# Count Plot (a.k.a. Bar Plot)
sns.countplot(x='Type 1', data=df, palette=pkmn_type_colors)
# Rotate x-labels
plt.xticks(rotation=-45)
نمودار فاکتور درک نقاط جدا از هم را با کلاسهای طبقه بندی شده آسان میسازد
# Factor Plot
g = sns.factorplot(x='Type 1',
y='Attack',
data=df,
hue='Stage', # Color by stage
col='Stage', # Separate by stage
kind='swarm') # Swarmplot
# Rotate x-axis labels
g.set_xticklabels(rotation=-45)
# Doesn't work because only rotates last plot
# plt.xticks(rotation=-45)
نمودار چگالی یا density plot چگونگی پراکندگی میان دو متغیر را نمایش میدهد.
# Density Plot
sns.kdeplot(df.Attack, df.Defense)
این نمودارها دادههای میان نمودار پراکندگی و هیستوگرام را برای نمایش اطلاعات جزیی بر اساس توزیعهای دو متغیره نشان میدهد.
# Joint Distribution Plot
sns.jointplot(x='Attack', y='Defense', data=df)
اگر دوست داری به یک متخصص داده کاوی اطلاعات با زبان پایتون تبدیل شوی و با استفاده از آن در بزرگترین شرکتها مشغول به کار شوی، شرکت در دوره دیتا ساینس را پیشنهاد میکنیم.
df = df.style.set_properties(**{
'background-color': 'grey',
'font-size': '20pt',
})