Python 項目實踐二(生成數據)第二篇


接着上節繼續學習,在本節中,我們將使用Python來生成隨機漫步數據,再使用matplotlib以引人矚目的方式將這些數據呈現出來。隨機漫步是這樣行走得到的路徑:每次行走都完全是隨機的,沒有明確的方向,結果是由一系列隨機決策決定的。你可以這樣認為,隨機漫步就是螞蟻在暈頭轉向的情況下,每次都沿隨機的方向前行所經過的路徑。

一 隨機漫步

1 創建RandomWalk()類

為模擬隨機漫步,我們將創建一個名為RandomWalk的類,它隨機地選擇前進方向。這個類需要三個屬性,其中一個是存儲隨機漫步次數的變量,其他兩個是列表,分別存儲隨機漫步經過的每個點的x和y坐標。代碼如下:

from random import choice

class RandomWalk() :
    '''一個生成隨機漫步數的類'''
    def __init__(self,num_points=50000):
        '''初始化隨機漫步的屬性'''
        self.num_points = num_points

        #所有隨機漫步都始於(0,0)
        self.x_values = [0]
        self.y_values =[0]
            

2 選擇方向

我們將使用fill_walk()來生成漫步包含的點,並決定每次漫步的方向,如下所示。請將這個方法添加到random_walk.py中:

 def fill_walk(self):
        #計算隨機漫步包含的所有點

        #不斷漫步,直到列表達到指定的長度
        while len(self.x_values) < self.num_points :

            #決定前進方向以及沿着個方向前進的距離
            x_direction = choice([1,-1])
            x_distance = choice([0,1,2,3,4])
            x_step = x_direction*x_distance

            y_direction = choice([1,-1])
            y_distance = choice([0,1,2,3,4])
            y_step = y_direction*y_distance

            #拒絕原地踏步
            if x_step == 0 and y_step ==0 :
                continue

            #計算下一個點的x和y值
            next_x= self.x_values[-1] + x_step
            next_y= self.y_values[-1] + y_step

            self.x_values.append(next_x)
            self.y_values.append(next_y)

代碼注釋的很清楚了,我再強調幾點:

(1)我們建立了一個循環,這個循環不斷運行,直到漫步包含所需數量的點。

(2)如何模擬四種漫步決定:向右走還是向左走?沿指定的方向走多遠?向上走還是向下走?沿選定的方向走多遠?

3 繪制隨機漫步的圖像

import matplotlib.pyplot as plt

from random_walk import RandomWalk

while True : 
    random_walk = RandomWalk()
    random_walk.fill_walk()
    plt.figure(figsize=(10,6))
    point_numbers = list(range(random_walk.num_points))
    plt.scatter(random_walk.x_values,random_walk.y_values,c=point_numbers,cmap=plt.cm.Blues,edgecolor="none",s=1)

    # 突出起點和終點
    plt.scatter(0, 0, c='green', edgecolors='none', s=100)
    plt.scatter(random_walk.x_values[-1], random_walk.y_values[-1], c='red', edgecolors='none',
    s=100)

    #隱藏坐標軸
    plt.axes().get_xaxis().set_visible(False)
    plt.axes().get_yaxis().set_visible(False)
    plt.show()

    input_flag = input("是否結束?(Y/N)")

    if input_flag == "Y" :
        break

 運行效果圖如下:

注意幾點:

(1)模擬多次隨機漫步:每次隨機漫步都不同,因此探索可能生成的各種模式很有趣。要在不多次運行程序的情況下使用前面的代碼模擬多次隨機漫步,一種辦法是將這些代碼放在一個while循環中。

(2)給點着色:我們將使用顏色映射來指出漫步中各點的先后順序,並刪除每個點的黑色輪廓,讓它們的顏色更明顯。為根據漫步中各點的先后順序進行着色。

(3)重新繪制起點和終點:,可在繪制隨機漫步圖后重新繪制起點和終點。我們讓起點和終點變得更大,並顯示為不同的顏色,以突出它們。

(4)隱藏坐標軸:為修改坐標軸,使用了函數plt.axes()來將每條坐標軸的可見性都設置為False。隨着你越來越多地進行數據可視化,經常會看到這種串接方法的方式。

(5)增加點數:增大num_points的值,並在繪圖時調整每個點的大小。

(6)調整尺寸以適合屏幕:函數figure()用於指定圖表的寬度、高度、分辨率和背景色。你需要給形參figsize指定一個元組,向matplotlib指出繪圖窗口的尺寸,單位為英寸。

二 使用Pygal模擬擲骰子

在本節中,我們將使用Python可視化包Pygal來生成可縮放的矢量圖形文件。對於需要在尺寸不同的屏幕上顯示的圖表,這很有用,因為它們將自動縮放,以適合觀看者的屏幕。如果你打算以在線方式使用圖表,請考慮使用Pygal來生成它們,這樣它們在任何設備上顯示時都會很美觀。

在這個項目中,我們將對擲骰子的結果進行分析。擲6面的常規骰子時,可能出現的結果為1~6點,且出現每種結果的可能性相同。然而,如果同時擲兩個骰子,某些點數出現的可能性將比其他點數大。為確定哪些點數出現的可能性最大,我們將生成一個表示擲骰子結果的數據集,並根據結果繪制出一個圖形。

1 安裝Pygal

python -m pip install --user pygal

2 創建Die類

from random import randint

class Die():
    '''表示一個骰子的類'''

    def __init__(self,num_sides=6):
        '''骰子默認6個面'''
        self.num_sides=num_sides

    def roll(self):
        #返回一個1-面數之間的隨機值
        return randint(1,self.num_sides)

3 擲篩子

使用這個類來創建圖表前,先來擲D6骰子,將結果打印出來,並檢查結果是否合理:

from die import Die

die=Die()

results=[]

for roll_num in range(100) :
    result=die.roll()
    results.append(result)

print(results)

結果如下:

4 分析結果

為分析擲一個D6骰子的結果,我們計算每個點數出現的次數:

from die import Die

die=Die()

results=[]

for roll_num in range(1000) :
    result=die.roll()
    results.append(result)

#分析結果
frequencies=[]
for value in range(1,die.num_sides+1) :
    frequency=results.count(value)
    frequencies.append(frequency)

print(frequencies)

結果如下:[156, 171, 151, 173, 181, 168]

結果看起來是合理的:我們看到了6個值——擲D6骰子時可能出現的每個點數對應一個;我們還發現,沒有任何點數出現的頻率比其他點數高很多。下面來可視化這些結果。

5 繪制立方圖

from die import Die
import pygal

die=Die()

results=[]

for roll_num in range(1000) :
    result=die.roll()
    results.append(result)


#分析結果
frequencies=[]
for value in range(1,die.num_sides+1) :
    frequency=results.count(value)
    frequencies.append(frequency)

#print(frequencies)

#對結果進行可視化
hist = pygal.Bar()

hist.title= "Results of rolling one D6 1000 times."
hist.x_labels=['1','2','3','4','5','6']
hist.x_title = "Result"
hist.y_title = "Frequency of Result"

hist.add("D6",frequencies)
hist.render_to_file("die_visual.svg")

為創建條形圖,我們創建了一個pygal.Bar()實例,並將其存儲在hist中,我們設置hist的屬性title(用於標示直方圖的字符串),將擲D6骰子的可能結果用作x軸的標簽,並給每個軸都添加了標題,我們使用add()將一系列值添加到圖表中(向它傳遞要給添加的值指定的標簽,還有一個列表,其中包含將出現在圖表中的值)。最后,我們將這個圖表渲染為一個SVG文件,這種文件的擴展名必須為.svg。
要查看生成的直方圖,最簡單的方式是使用Web瀏覽器。如下圖:

6 同時擲兩個骰子

 每次擲兩個骰子時,我們都將兩個骰子的點數相加,並將結果存儲在results中。請復制die_visual.py並將其保存為dice_visual.py,再做如下修改:

from die import Die
import pygal

die_1=Die()
die_2=Die()

results=[]

for roll_num in range(1000) :
    result=die_1.roll() + die_2.roll() 
    results.append(result)


#分析結果
frequencies=[]
max_result = die_1.num_sides + die_2.num_sides

for value in range(2,max_result+1) :
    frequency=results.count(value)
    frequencies.append(frequency)

#print(frequencies)

#對結果進行可視化
hist = pygal.Bar()

hist.title= "Results of rolling two D6 1000 times."
hist.x_labels=['1','2','3','4','5','6''7','8','9','10','11','12']
hist.x_title = "Result"
hist.y_title = "Frequency of Result"

hist.add("D6+D6",frequencies)
hist.render_to_file("die_visual.svg")

結果如下:

也可以擲不同的骰子,就不在詳解了!未完待續!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM