ম্যাটপ্লটলিব

এই পোস্টটা লিখে সেইরকম মজা পাবো বুঝা যাচ্ছে। আপনি একটা টান দিয়ে উপর থেকে নিচে টানলেই বুঝতে পারবেন কেন। গতকালের পোস্ট ছিল মূলত পাইথন ডাটা স্ট্যাকের একেবারে নিচের দিকের কনসেপ্ট নিয়ে, অর্থাৎ নামপাই নিয়ে। আজকে হবে মূলত উপরের দিকের লাইব্রেরি, ম্যাটপ্লটলিব নিয়ে কিছু কথাবার্তা। মাঝখানের স্ট্যাক নিয়েই যত ঝামেলা হবে, অই অঞ্চল নির্ণীত হবে আপনি ডাটা দিয়ে কি করতে চান সেটির উপর এবং বহু এলগরিদম, বিষয় সাপেক্ষ আলোচনা, এবং আপাতদৃষ্টিতে মাথার উপর দিয়ে যাওয়া ফাংশন চলে আসবে এবং লিখতে গিয়েও ভাল প্যারা খাবো। কিন্তু আপাতত আমরা সহজবোধ্য ব্যাপারগুলো আলোচনা করি এবং আমাদের কন্টেক্সটে আসি, যা হল ম্যাটপ্লটলিব।

ম্যাটপ্লটলিব হল খুব সহজে পাইথনের মাধ্যমে প্লটিং করার জন্য একটি লাইব্রেরি, এর জনক জন হান্টার (১৯৬৮ - ২০১২), আমাদের মাঝে নেই এবং তাঁর মৃত্যু পাইথন কমুনিটির জন্য ছিল বড় একটি লস। তাঁর ভাষায়, "Matplotlib makes easy things easy and hard things possible"। আর আমরা এখন দেখব তা কি করে সত্য।

আমার এখানে দেখান প্লটগুলো একটু কার্টুন মার্কা হবে, আপনারা যারা সিরিয়াস প্রকৃতির তাঁরা আমার কোডের plt.xkcd লিখাটি রিমুভ করে দিবেন, দেখবেন সব প্লট সিরিয়াস হয়ে যাবে। এই পোস্টটিও আগের নামপাইের পোস্টের মত ipython ভিত্তিক হবে এবং রান করার নিয়মও একই রকম। pip install matplotlib চলবে লিনাক্সবাসিদের জন্য, উইন্ডোজ ইউজাররা Python (x,y) ইন্সটল করে নিবেন অথবা এইখান থেকে শিখে নিবেন, সেটার জন্য আমি তও ফেইসবুকে আছিই, তাই সেই বিষয়ে প্যাঁচাল না পারলাম এখানে এবং কোডের দিকে মননিবেশ করলাম। শুরু করছি এখন।

ম্যাটপ্লটলিব দিয়ে প্লট করতে হলে প্রথমে আপনাকে বুঝতে হবে এর Figure অবজেক্টকে। এর উপরি আপনি আপনার প্লট অ্যাড করবেন। আপনার কারয প্রণালি হবে এরকম-

  • প্রথমে করুন ইম্পোরট (as plt একটি কনভেনশন) from matplotlib import pyplot as plt
  • এই plt কন্ট্রোল করবে আপনার প্লট কেমন হবে। আমি plt.xkcd() এর মাধ্যমে বলে নিলাম যে আমার প্লটগুলি xkcd এর আদলে হবে, YMMV :P
  • Figure কে আপনি নাম্বারের মাধ্যমে প্রকাশ করতে পারবেন, আবার প্রতিটি ফিগারে অনেকগুলি subplot থাকতে পারে যা আপনি add_subplot এর মাধ্যমে তৈরি করবেন। যেমন- figure.add_subplot(2, 2, 1) বলতে বুঝায়, আপনার figure হল 2X2 আর আপনি ৪ টির মধ্যে প্রথমটি সেলেক্ট করলেন। অনেকগুলি subplot তৈরির পর আপনি যখন প্লট করা শুরু করবেন, সবচেয়ে শেষের প্লটটিতে আঁকা হবে। আপনি subplot ফাংশনের মাধ্যমে অথবা প্রতিটি subplot কে একটি হ্যান্ডল দিয়ে ধরে ওখানে plot ফাংশন কল করবেন।
  • plot, scatter, bar, barh, axes ইত্যাদি ফাংশন রয়েছে আপনার প্লট করতে সাহায্য করার জন্য।
  • উপরোক্ত ফাংশনগুলি পাইথন লিস্টকে চিনে, কিন্তু নামপাই ব্যবহার করা হয় সাধারণত (প্রায় সবসময়ে)। এর কারণ, নামপাইয়ের অ্যারে অনেক দ্রুত, আর এর কিছু ফাংশন (যা অ্যারের প্রতি সদস্যের উপর কাজ করে) plot ফাংশনের সুন্দর সহযোগী।
  • plot বলুন আর scatter বলুন, সবাই x, y অক্ষ বরাবর, আর কিছু কনফিগারেশন ভেরিয়েব্ল আছে, যা ফিল আপ করলেই আপনি পাবেন আপনার প্লট। যেমন, plt.plot(np.array([1, 2, 3]), np.array([5, 6, 7]), linestyle="---", color="g")
  • আপনি এখানে লাইভ দেখতে পারবেন অথবা ফাইলে সেভ করতে পারবেন। ফাইল ফরম্যাট হতে পারে PDF, SVG, PNG, JPG ইত্যাদি।
  • ম্যাটপ্লটলিবের চিত্রগুলিকে এভাবে ইনলাইন দেখার জন্য আপনি কমান্ড লাইনে লিখবেন ipython notebook --pylab=inline

এইতো, খুব ক্ষুদ্র ম্যাটপ্লটলিব পরিচিতি। এইবার প্যাঁচাল কম, কোড বেশি ;-)

In [2]:
# একদম সহজ উদাহরণ, পাইথন লিস্টের মাধ্যমে!!! 

import random
import math

import numpy as np
from matplotlib import pyplot as plt

plt.xkcd() # এই লাইনটিকে সরিয়ে দিন যদি কার্টুন না চান :P 

plt.plot(range(10), range(10)) # ১ - ১ ম্যাপিং হয় প্রথম ও দ্বিতীয় প্যারামেটারের মধ্যে 
Out[2]:
[<matplotlib.lines.Line2D at 0xbbb21cc>]
In [1]:
figure_0 = plt.figure(0)

ax1 = figure_0.add_subplot(2, 2, 1) # প্রথম সাবপ্লট উপর, বাম 
ax2 = figure_0.add_subplot(2, 2, 2) #  দ্বিতীয় সাবপ্লট উপর ডান 
ax3 = figure_0.add_subplot(2, 2, 3) # তৃতীয় সাবপ্লট নিচ বাম 
ax4 = figure_0.add_subplot(2, 2, 4) # চতুর্থ সাবপ্লট নিচ ডান 

ax1.plot(np.random.randn(100).cumsum(), 
         linestyle="--", # ডটগুলিকে কিভাবে যুক্ত করব? 
         color="black") # যুক্তরেখার রঙ কি হবে? 
ax2.hist(np.random.randn(100),
         color="green")
ax3.scatter(np.random.randn(500), 
            np.random.randn(500), 
            color="red")
ax4.barh(np.arange(5), 
         np.arange(5), 
         alpha=0.3) # কতটুকু ট্রান্সপারেন্ট হবে? 

figure_1 = plt.figure(1)

ax1 = figure_1.add_subplot(2, 1, 1)
ax2 = figure_1.add_subplot(2, 1, 2)

ax1.plot(np.arange(1, 100, 0.2), 
         np.arange(1, 100, 0.2)**2)
ax2.plot(np.random.randn(10).cumsum(), 
         linestyle="dashed", 
         color="orange", 
         marker="o") # প্রতিটি পয়েন্ট কিভাবে চিহ্নিত হবে? 

figure_2 = plt.figure(2)
ax1 = figure_2.add_subplot(1, 1, 1,)

ax1.plot(np.random.randn(50).cumsum(),
         linestyle="-",
         drawstyle="steps-post", # স্টেপে স্টেপে উঠবে 
         label="steps-post")

ax1.plot(np.random.randn(50).cumsum(),
         linestyle="--",
         marker="o")
Out[1]:
[<matplotlib.lines.Line2D at 0xb91238c>]

এই লিঙ্কে আপনি পাবেন সমস্ত প্রপার্টি এবং এদের মান। যেমন linestyle, linewidth, color, alpha, animated, label, zorder ইত্যাদি।

টিক, লেবেল, ও লেজেন্ড

In [3]:
figure = plt.figure()

ax = figure.add_subplot(1, 1, 1)
ax.set_title("Random Stuff")

ax.set_xlim(100) # X সরবচ্চ কত হবে? 
ax.set_ylim(100) # Y সরবচ্চ কত হবে?

ax.set_xticks(range(0, 100, 10)) # X বরাবর কোন কোন পয়েন্টে লেবেল থাকবে? 
ax.set_yticks(range(0, 100, 25)) # Y বরাবর কোন কোন পয়েন্টে লেবেল থাকবে?
ax.set_xticklabels(range(0, 100, 10), # টিক গুলতে কি লিখা থাকবে? 
                   rotation=30, # লিখা ঘুরবে কতটুকু? 
                   fontsize="small") # লিখার সাইজ কেমন হবে? 
ax.set_yticklabels(["As good as none", "50/50", "Loads", "Huge"],
                   fontsize="large")

xs = np.array([random.randrange(1, 100) for i in range(100)])

ax.scatter(xs,
           xs + np.random.randn(100)**2,
           label="Lower")

ax.scatter(xs+5,
           xs - np.random.randn(100)**2,
           color="red",
           label="Higher")

ax.legend(loc="best") # উপরের প্লটগুলর লেবেল চলে আসবে, সবচেয়ে ভাল জায়গায় বসান হবে। 
Out[3]:
<matplotlib.legend.Legend at 0xbdb504c>
In [4]:
figure = plt.figure()

ax = figure.add_subplot(1, 1, 1)
rect = plt.Rectangle((0.2, 0.75),
                      0.4, 
                      0.15, 
                      color='b', 
                      alpha=0.3)
circ = plt.Circle((0.7, 0.2), 
                  0.15, 
                  color='g', 
                  alpha=0.3)
pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]],
                   color='k', 
                   alpha=0.5)

ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)
Out[4]:
<matplotlib.patches.Polygon at 0xbef0a4c>

উদাহরণ ১ হিস্টোগ্রাম (ডকুমেন্টেশন থেকে নেওয়া)

In [5]:
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

# the histogram of the data
plt.hist(x, 50, normed=1, facecolor='k', alpha=0.4)


plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$') # আপনি এই লিঙ্ক থেকে শিখে নিন কিভাবে ফর্মুলা লিখতে হয় http://matplotlib.org/users/mathtext.html
plt.axis([40, 160, 0, 0.03]) # অক্ষ কোথায় শুরু ও শেষ?
plt.show()

উদাহরণ ২ গ্রাফ প্লট (সমীকরণ থেকে)

In [6]:
def graph(plotter, formulae, x_range):
    for formula in formulae:
        x = np.array(x_range)  
        y = formula(x)
        plotter.plot(x, y)
        
figure = plt.figure()

graph(figure.add_subplot(2, 1, 1,),
      [lambda x: x**2,
       lambda x: x**3,
       lambda x: x**4],
      range(-10, 10))

graph(figure.add_subplot(2, 1, 2,),
      [lambda x: x + 10,
       lambda x: 2*x + 14,
       lambda x: x],
      range(0, 5))

উদাহরণ ৩ পাই চার্ট

In [7]:
browsers = ['Chrome', 'IE', 'Firefox', 'Others']
usage = [59.3, 8.8, 25.1, 5.5]
colors = ['yellowgreen', 'black', 'lightskyblue', 'gold',]
explode = (0, 0.3, 0, 0) # ২ নাম্বার কে ফাটাব! অর্থাৎ বের হয়ে থাকবে 

## brosers, usage, colors and explode এর সাইজ যেন সমান থাকে, এরা এক সাথে zipped হবে। 

plt.pie(usage, 
        explode=explode, 
        labels=browsers, 
        colors=colors,
        autopct='%1.1f%%', 
        shadow=True)

plt.legend(loc="best", fontsize="small")

# annotate এর মাধ্যমে আপনি টেক্সট লিখতে পারবেন প্লটে। 
plt.annotate('Kill it before it lays more eggs',
        xy=(-0.6, -0.9), # উৎস 
        arrowprops=dict(arrowstyle='->'), # কিভাবে চিহ্নিত হবে?  
        xytext=(-4, 0)) # টেক্সট এর পজিশান

plt.axis('equal')
plt.show()

উদাহরণ ৪ কসাইন প্লট

In [8]:
figure = plt.figure()

ax = figure.add_subplot(1, 1, 1)

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)

ax.annotate('local max', xy=(2, 1), xytext=(3, 1.5),
            arrowprops=dict(facecolor='black', shrink=0.05))

ax.set_ylim(-2,2)

ax.plot(t, s, lw=2)
Out[8]:
[<matplotlib.lines.Line2D at 0xc4211ac>]

উদাহরণ ৫ আরেকটি উদাহরণ (এটিও ডকুমেন্টেশন থেকে মারা)

In [9]:
a = np.arange(0,3, .02)
b = np.arange(0,3, .02)
c = np.exp(a)
d = c[::-1]

figure = plt.figure()
ax = figure.add_subplot(1, 1, 1)

ax.plot(a, c, 'k--', label='Model length')
ax.plot(a, d, 'k:', label='Data length')
ax.plot(a, c+d, 'k', label='Total message length')

legend = ax.legend(loc='upper center', shadow=True)

frame  = legend.get_frame()
frame.set_facecolor('0.90')

for label in legend.get_texts():
    label.set_fontsize('large')

for label in legend.get_lines():
    label.set_linewidth(1.5)
plt.show()

বলে না, "A picture is worth a thousand words (so are codes)", তাই এই পস্তে লিখেছি কম, দেখিয়েছি বেশি।আমার ইচ্ছা ছিল আরও গদ্য লিখার, কিন্তু শেষ পর্যন্ত আমার আলস্য জিতেছে, তাই এখানেই বন্ধও করতে হল।

কিন্তু নামপাই অথবা ম্যাটপ্লটলিবের শেষ কিন্তু এখানে মোটেও না, এখানে তও মাত্র শুরু করা হল, অত্যন্ত বেসিক জিনিসপত্র। আগামীতে আরও থাকবে, আর পরিচিত হবেন pandas এর সাথে।