2007/05/03

Python 初體驗 - 好吃不黏牙!

這幾天上課的老師出了幾個需要畫圖的習題,大致上是要用常態分佈取樣幾個點,X 軸跟 Y 軸給不同的 mean 跟 standard deviation 繪製圖形。另外一個作業是繪出高斯分佈取樣的點的 probability density function。 剛開始還考慮用 perl 來解題,後來想說順便學一下 python,就試著用它來寫寫看。

TimChen 要了些初學者用的網站,就開始看著 咬一口 python 程式語言這本線上書籍學 Python。看完幾頁之後,就發現 python 比想像中的好上手,程式碼也很簡潔。接下來就開始思考要如何解題。

第一個,我需要有高斯分佈的取樣點,馬上查了 "python gaussian distribution",有內建函式!很好很好,馬上就先解決取樣的問題。取樣完後需要 gnuplot 來畫圖。剛開始我打算先輸入到檔案裡面,再用 os module 來呼叫 gnuplot。在這個時候我又查了 "python gnuplot",沒想到又有!原來 python 有提供 gnuplot 的橋接,只要安裝 python-gnuplot 就可以使用了。所以這個問題就解決了,大約花了 30 行左右:

#!/usr/bin/env python

import random, os, Gnuplot

mean = 3
strdev = 10
ns = [10, 100, 1000, 10000]
g = Gnuplot.Gnuplot()
g('set multiplot')
g('set size 0.5,0.5')

for i in range(0, 4):
gauss = list()
for j in range(0, ns[i]):
gauss.append(list())
gauss[j].append(random.gauss(mean, strdev))
gauss[j].append(random.gauss(mean, strdev))

if i == 0:
g('set origin 0,0.5')
elif i == 1:
g('set origin 0.5,0.5')
elif i == 2:
g('set origin 0,0')
else:
g('set origin 0.5,0')

g.plot(gauss)

g('unset multiplot')
raw_input('Please press return to continue...\n')


Screenshot-Gnuplot

Cool, 很好用。第二題要畫高斯分佈的 PDF,算這東西真的還蠻花時間的,後天就要交作業還是抱一下佛腳好了…。搜尋一下發現這東西,可以直接算出 PDF,當然又是直接拿來用…。

#!/usr/bin/env python

import statistics, random, Gnuplot

gauss = list()
gauss2 = list()
gpdf = list()
gpdf2 = list()
g = Gnuplot.Gnuplot()

for i in range(0, 1000):
gauss.append(random.gauss(-2, 1))
gauss2.append(random.gauss(2, 2))
#gauss.append(random.gauss(2, 1))
#gauss2.append(random.gauss(-2, 1))

y, x = statistics.pdf(gauss, kernel = 'Gaussian')
w, z = statistics.pdf(gauss2, kernel = 'Gaussian')

for i in range(0, len(x)):
gpdf.append(list())
gpdf[i].append(x[i])
gpdf[i].append(y[i])

for i in range(0, len(w)):
gpdf2.append(list())
gpdf2[i].append(z[i])
gpdf2[i].append(w[i])

g.plot(gpdf, gpdf2)
raw_input('Please press return to continue...\n')


Screenshot-Gnuplot-1 Screenshot-Gnuplot-2

作業完成!

結論,Python 真的是好物阿!如果有寫其他程式語言的經驗,Python 是相當好學的東西!

4 則留言 :

  1. 請教一下,python 有個一維 list, 例如 [0.8, 1.7, 0.8, 0.7, 2.0,1.5] , 我要如何用gnuplot畫出 x軸是data 間距,y軸是 count, 以這個例子來說,我想要 x 軸是 0~1 的有3筆, 1~2 的有2筆,2~3 的有1筆,要如何做呢?

    回覆刪除
  2. 上網找一下資料看看
    http://gist.github.com/466538

    回覆刪除
  3. 感謝你,但好像跟我想的不同。python 2.7 有個新的 Counter 可以算次數, 是 dict 的subclass, 但是plot 好像不吃 dict,Counter我猜應該也不行
    g = Gnuplot.Gnuplot ()
    d={'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}
    g.plot (d)

    另外發現一個matplotlib有提供一個 histogram, 看起來好像有點機會

    回覆刪除
  4. 或許作些正規化再丟進 gnuplot 就可以了 :)

    回覆刪除