هیستوگرام‌ها در کتابخانه Matplotlib پایتون

در مقاله پیشین در مورد نحوه کار با کتابخانه محبوب Matplotlib، و مفاهیم اصلی موجود در آن نکاتی گفته شد در صورتیکه با این کتابخانه آشنایی ندارید توصیه می‌شود ابتدا مقاله زیر را مطالعه کنید

در این آموزش با نمودارهای هیستوگرام در این کتابخانه قدرتمند که شما را به نمایش بهتر داده‌هایتان کمک خواهد کرد آشنا خواهیم شد.


هیستوگرام‌ها یا Histograms

هیستوگرام‌ها شکلی از نمایش داده هستند که داده‌ها را بر اساس توزیع عددی آن‌ها ارائه می‌دهند. در واقع نوعی نمودار میله‌ایست که محور X نشان دهنده دامنه توزیع داده و محور Y نمایانگر فراوانی داده در یک بازه معین می‌باشد. برای ایجاد یک هیستوگرام در کتابخانه Matplotlib لازم است ابتدا داده‌های خود را در یک آرایه لیست کنیم. سپس به کمک تابع hist از pyplot هیستوگرام مورد نظر خود را خروجی بگیریم. در مثال زیر تعداد 10000 عدد تصادفی توسط تابع random.randn در توزیع نرمال استاندارد ایجاد و در یک هیستوگرام با 20 دسته  در دامنه توزیع داده نمایش داده شده است:

data = np.random.randn(10000)
plt.hist(data, bins=20)
plt.show()
Image for post
Image for post

بدیهی است هر چه تعداد دسته‌ها بیشتر باشد نمودار حالت پیوسته‌تری خواهد داشت. 

data = np.random.randn(100000)

fig, axs = plt.subplots(2, 2,  figsize =(8, 5))

axs[0,0].hist(data, bins=5)
axs[0,1].hist(data, bins=15)
axs[1,0].hist(data, bins=30)
axs[1,1].hist(data, bins=50)
    
plt.show()
Image for post
Image for post

در مثال زیر نیز نمودار فراوانی یک آرایه تصادفی از کاراکترها را در هیستوگرام به نمایش درآمده است:

data = ['a', 'a', 'a', 'a', 'b', 'b',
       'c', 'c', 'c', 'd', 'e', 'e',
       'e', 'e', 'e', 'f', 'f', 'f']

plt.hist(data, bins=[0,1,2,3,4,5,6], align='left', 
        color='blue', edgecolor='black')
plt.show()
Image for post
Image for post

ایجاد ساختار نمایشی متفاوت با colormap

کالرمپ‌ها(colormap) اشیایی هستند که اعداد را به رنگ تصویر می‌کنند. در Matplotlib تعداد بسیاری colormap بصورت built-in وجود دارد. برای نمونه کالرمپ grey، صفر را سیاه و یک را سفید تصویر می‌کند و یا کالرمپ jet صفر را آبی و یک را قرمز تصویر می‌کند. در زیر چند نمونه از کالرمپ‌ها لیست شده است:

 

Image for post
Image for post
Image for post
Image for post

 

برای نمایش بهتر هیستوگرام با کمک colormapها می‌توان برای هر ستون از نمودار با توجه به میزان فراوانی یک رنگ از colormap به آن اختصاص دهیم. برای این منظور تلاش خواهیم کرد برای اولین نمودار هیستوگرام در این مقاله بصورت زیر نمایش بهتری ایجاد ‌کنیم:

frequencies, bins, patches = plt.hist(data, bins=20)

frequencies لیستی از فراوانی هر دسته، bins یک آرایه از نقاط ابتدایی هر دسته‌ روی محور x و patches لیستی از اشیاء matplotlib.patches.Rectangle برای نمایش مستطیل‌های گرافیکی در نمودار می‌باشند.

ابتدا بصورت زیر فراوانی را به بازه [0,1] تصویر می‌کنیم:

fracs = frequencies/ frequencies.max()

سپس با کمک تابع zip برای هر شی ستون از هیستوگرام با توجه به مقدار تبدیل شده در آرایه fracs یک رنگ در نظر می‌گیریم. 

for thisfrac, thispatch in zip(fracs, patches):
    color = plt.cm.viridis(thisfrac)
    thispatch.set_facecolor(color)

تابع zip(iterator1, iterator2, iterator3, ...) یک شی zip که یک متغیر tuples می‌باشد را بازمی‌گرداند. که اولین عضو آن اولین عناصر از ورودی‌های این تابع است و باقی عناصر به همین صورت خواهند بود.

تمامی موارد فوق بصورت زیر نتیجه خواهد داد:

import matplotlib.pyplot as plt 
import numpy as np 

data = np.random.randn(10000)

fig, axs = plt.subplots(1, 1,  figsize =(4, 5))

frequencies, bins, patches = axs.hist(data, bins=20) 

fracs = frequencies/frequencies.max()

for thisfrac, thispatch in zip(fracs, patches):
    color = plt.cm.viridis(thisfrac)
    thispatch.set_facecolor(color)
    
plt.show()
Image for post
Image for post

با افزودن مواردی دیگر خروجی نهایتا می‌تواند بصورت زیر هم باشد:

import matplotlib.pyplot as plt 
import numpy as np

data = np.random.randn(10000)
fig, axs = plt.subplots(1, 1,  figsize =(10, 7), tight_layout = True)

# Remove axes splines  
for s in ['top', 'bottom', 'left', 'right']:  
   axs.spines[s].set_visible(False) 

# Remove x, y ticks 
axs.xaxis.set_ticks_position('none')  
axs.yaxis.set_ticks_position('none')  

# Add padding between axes and labels  
axs.xaxis.set_tick_params(pad = 5)  
axs.yaxis.set_tick_params(pad = 10)

# Add x, y gridlines  
axs.grid(b=True, color='grey', linestyle='-.', 
		linewidth=0.5, alpha=0.6)  
		
# Creating histogram 
frequencies, bins, patches = axs.hist(data, bins=20)

# Setting color 
fracs = frequencies/frequencies.max()
for thisfrac, thispatch in zip(fracs, patches):
   color = plt.cm.viridis(thisfrac)
   thispatch.set_facecolor(color)
   
# Adding extra features     
plt.xlabel("X-axis") 
plt.ylabel("y-axis") 
plt.legend(['distribution'] ) 
plt.title('Customized histogram')

plt.show()
Image for post
Image for post

این امکان نیز در کتابخانه Matplotlib فراهم شده است که بتوانیم چندین هیستوگرام را با یکدیگر در یک نمودار مقایسه کنیم برای این منظور تنها کافی است که دیتاهای متفاوت را در یک آرایه 2-بعدی لیست کنیم. به مثال زیر دقت کنید:

data1 = np.random.randn(10000)
data2 = np.random.randn(10000)

colors = ['#D55E00', '#56B4E9']
names = ['1st distribution', '2nd distribution']

plt.hist([data1, data2], bins=15, color=colors, label=names)

plt.legend()
plt.show()
Image for post
Image for post

همانطور که مشاهده می‌کنید برای نمایش بهتر با استفاده از دو خاصیت label و color برای هر هیستوگرام نام و رنگ متفاوتی در نظر گرفته شده است. همچنین می‌توان نمودار را بصورت stack دربیاورید برای این منظور تنها کافیست خاصیت stacked را برابر مقدار True قرار دهید:

Image for post
Image for post

تابع هیستوگرام در کتابخانه Matplotlib اشکال متفاوتی دارد که برای اعمال هر یک از آنها در هیستوگرام‌های خود لازم است خاصیت histtype تعیین ‌شود. مقادیر قابل قبول 'barstacked' ،'step' ،'stepfilled' و 'bar' می‌باشند که در مثال زیر تمامی حالت‌های ممکن را ترسیم کرده‌ام:

data1 = np.random.randn(400)
data2 = np.random.randn(500) + 3
data3 = np.random.randn(450) + 6
data4a = np.random.randn(200) + 9
data4b = np.random.randn(100) + 10

plt.hist(data1, bins=5, color='g', edgecolor='black', alpha=0.75, label='bar hist') # default histtype='bar'
plt.hist(data2, color='b', edgecolor='black', alpha=0.65, histtype='stepfilled', label='stepfilled hist')
plt.hist(data3, color='r', histtype='step', label='step hist')
plt.hist((data4a, data4b), color=('r','m'), alpha=0.55, histtype='barstacked', label=('barstacked a', 'barstacked b'))

plt.xlabel("Value")
plt.ylabel("Frequency")
plt.legend()
plt.grid(True)
plt.show()
Image for post
Image for post

ترسیم هیستوگرام 2-بعدی

برای ترسیم گراف 2-بعدی تنها چیزی که نیاز دارید دو بردار با طول یکسان مربوط به هر محور هیستوگرام است.

fig, axs = plt.subplots(1, 1,figsize=(5,5))

data1 = np.random.randn(10000)
data2 = np.random.randn(10000)

axs.hist2d(data1, data2, bins=40)
plt.show()
Image for post
Image for post

این امکان نیز وجود دارد برای هر محور تعداد سفارشی‌سازی شده‌ای دسته تعریف کنیم:

bins=(50,10)
bins=(50,10)
bins=(50,10)

نمودار چگالی

نمودار چگالی (Density Plot) نسخه هموار و پیوسته‌ای از هیستوگرام است. برای ترسیم این شکل از نمودارها روش سرراستی در کتابخانه matplotlib وجود ندارد. برای این منظور می‌توانیم از کتابخانه seaborn استفاده کنید. البته امکان ترسیم این شکل از نمودارها با کمک کتابخانه pandas نیز وجود دارد که در مقاله آموزش pandas به آن اشاره خواهد شد.

import seaborn as sns

sns.set(style="darkgrid")

d1 = np.random.randn(1000)
d2 = np.random.randn(1000) + 3 

sns.histplot(data=d1, kde=True, label="data1", color="skyblue")
sns.histplot(data=d2, kde=True, label="data2", color="red")

plt.legend() 
plt.show()
Image for post
Image for post

در این مقاله با نمودار هیستوگرام که در گزارش‌ها و تحلیل‌های آماری بسیار مورد استفاده قرار می‌گیرد آشنا شدید در مقاله بعد با نمودار polar از کتابخانه Matplotlib آشنا خواهید شد.