1. 程式人生 > >資料分析之numpy模組學習

資料分析之numpy模組學習

Python模組中的numpy,這是一個處理陣列的強大模組,而該模組也是其他資料分析模組(如pandas和scipy)的核心。

接下面將從這5個方面來介紹numpy模組的內容:

1)陣列的建立

2)有關陣列的屬性和函式

3)陣列元素的獲取--普通索引、切片、布林索引和花式索引

4)統計函式與線性代數運算

5)隨機數的生成

 

陣列的建立

numpy中使用array()函式建立陣列,array的首個引數一定是一個序列,可以是元組也可以是列表。

一維陣列的建立

可以使用numpy中的arange()函式建立一維有序陣列,它是內建函式range的擴充套件版。

In [1]: import numpy as np

In [2]: ls1 = range(10)

In [3]: list(ls1)

Out[3]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [4]: type(ls1)

Out[4]: range

 

In [5]: ls2 = np.arange(10)

In [6]: list(ls2)

Out[6]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [7]: type(ls2)

Out[7]: numpy.ndarray

通過arange生成的序列就不是簡簡單單的列表型別了,而是一個一維陣列。

 

如果一維陣列不是一個規律的有序元素,而是人為的輸入,就需要array()函式建立了。

In [8]: arr1 = np.array((1,20,13,28,22))

In [9]: arr1

Out[9]: array([ 1, 20, 13, 28, 22])

In [10]: type(arr1)

Out[10]: numpy.ndarray

上面是由元組序列構成的一維陣列。

 

In [11]: arr2 = np.array([1,1,2,3,5,8,13,21])    

In [12]: arr2

Out[12]: array([ 1,  1,  2,  3,  5,  8, 13, 21])

In [13]: type(arr2)

Out[13]: numpy.ndarray

上面是由列表序列構成的一維陣列。

 

二維陣列的建立

二維陣列的建立,其實在就是列表套列表或元組套元組。

In [14]: arr3 = np.array(((1,1,2,3),(5,8,13,21),(34,55,89,144)))

In [15]: arr3

Out[15]:

array([[  1,   1,   2,   3],

[  5,   8,  13,  21],

[ 34,  55,  89, 144]])

上面使用元組套元組的方式。

 

In [16]: arr4 = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])

In [17]: arr4

Out[17]:

array([[ 1,  2,  3,  4],

[ 5,  6,  7,  8],

[ 9, 10, 11, 12]])

上面使用列表套列表的方式。

對於高維陣列在將來的資料分析中用的比較少,這裡關於高維陣列的建立就不贅述了,構建方法仍然是套的方式。

 

上面所介紹的都是人為設定的一維、二維或高維陣列,numpy中也提供了幾種特殊的陣列,它們是:

In [18]: np.ones(3)  #返回一維元素全為1的陣列

Out[18]: array([ 1.,  1.,  1.])

 

In [19]: np.ones([3,4])  #返回元素全為1的3×4二維陣列

Out[19]:

array([[ 1.,  1.,  1.,  1.],

[ 1.,  1.,  1.,  1.],

[ 1.,  1.,  1.,  1.]])

 

In [20]: np.zeros(3) #返回一維元素全為0的陣列

Out[20]: array([ 0.,  0.,  0.])

 

In [21]: np.zeros([3,4]) #返回元素全為0的3×4二維陣列

Out[21]:

array([[ 0.,  0.,  0.,  0.],

[ 0.,  0.,  0.,  0.],

[ 0.,  0.,  0.,  0.]])

 

In [22]: np.empty(3) #返回一維空陣列

Out[22]: array([ 0.,  0.,  0.])

 

In [23]: np.empty([3,4]) #返回3×4二維空陣列

Out[23]:

array([[ 0.,  0.,  0.,  0.],

[ 0.,  0.,  0.,  0.],

[ 0.,  0.,  0.,  0.]])

 

有關陣列的屬性和函式

當一個數組構建好後,我們看看關於陣列本身的操作又有哪些屬性和函式:

In [24]: arr3

Out[24]:

array([[  1,   1,   2,   3],

[  5,   8,  13,  21],

[ 34,  55,  89, 144]])

 

In [25]: arr3.shape  #shape方法返回陣列的行數和列數

Out[25]: (3, 4)

 

In [26]: arr3.dtype  #dtype方法返回陣列的資料型別

Out[26]: dtype('int32')

 

In [27]: a = arr3.ravel()    #通過ravel的方法將陣列拉直(多維陣列降為一維陣列)

In [28]: a

Out[28]: array([  1,   1,   2,   3,   5,   8,  13,  21,  34,  55,  89, 144])

 

In [29]: b = arr3.flatten()  #通過flatten的方法將陣列拉直

In [30]: b

Out[30]: array([  1,   1,   2,   3,   5,   8,  13,  21,  34,  55,  89, 144])

兩者的區別在於ravel方法生成的是原陣列的檢視,無需佔有記憶體空間,但檢視的改變會影響到原陣列的變化。而flatten方法返回的是真實值,其值的改變並不會影響原陣列的更改。

通過下面的例子也許就能明白了:

In [31]: b[:3] = 0

In [32]: arr3

Out[32]:

array([[  1,   1,   2,   3],

[  5,   8,  13,  21],

[ 34,  55,  89, 144]])

通過更改b的值,原陣列沒有變化。

 

In [33]: a[:3] = 0

In [34]: arr3

Out[34]:

array([[  0,   0,   0,   3],

[  5,   8,  13,  21],

[ 34,  55,  89, 144]])

a的值變化後,會導致原陣列跟著變化。

 

 

In [35]: arr4

Out[35]:

array([[ 1,  2,  3,  4],

[ 5,  6,  7,  8],

[ 9, 10, 11, 12]])

 

In [36]: arr4.ndim   #返回陣列的維數

Out[36]: 2

 

In [37]: arr4.size   #返回陣列元素的個數

Out[37]: 12

 

In [38]: arr4.T  #返回陣列的轉置結果

Out[38]:

array([[ 1,  5,  9],

[ 2,  6, 10],

[ 3,  7, 11],

[ 4,  8, 12]])

如果陣列的資料型別為複數的話,real方法可以返回複數的實部,imag方法返回複數的虛部。

 

介紹完陣列的一些方法後,接下來我們看看陣列自身有哪些函式可操作:

In [39]: len(arr4) #返回陣列有多少行

Out[39]: 3

 

In [40]: arr3

Out[40]:

array([[  0,   0,   0,   3],

[  5,   8,  13,  21],

[ 34,  55,  89, 144]])

 

In [41]: arr4

Out[41]:

array([[ 1,  2,  3,  4],

[ 5,  6,  7,  8],

[ 9, 10, 11, 12]])

 

In [42]: np.hstack((arr3,arr4))

Out[42]:

array([[  0,   0,   0,   3,   1,   2,   3,   4],

[  5,   8,  13,  21,   5,   6,   7,   8],

[ 34,  55,  89, 144,   9,  10,  11,  12]])

橫向拼接arr3和arr4兩個陣列,但必須滿足兩個陣列的行數相同。

 

In [43]: np.vstack((arr3,arr4))  

Out[43]:

array([[  0,   0,   0,   3],

[  5,   8,  13,  21],

[ 34,  55,  89, 144],

[  1,   2,   3,   4],

[  5,   6,   7,   8],

[  9,  10,  11,  12]])

縱向拼接arr3和arr4兩個陣列,但必須滿足兩個陣列的列數相同。

 

In [44]: np.column_stack((arr3,arr4))    #與hstack函式具有一樣的效果

Out[44]:

array([[  0,   0,   0,   3,   1,   2,   3,   4],

[  5,   8,  13,  21,   5,   6,   7,   8],

[ 34,  55,  89, 144,   9,  10,  11,  12]])

 

In [45]: np.row_stack((arr3,arr4))    #與vstack函式具有一樣的效果

Out[45]:

array([[  0,   0,   0,   3],

[  5,   8,  13,  21],

[ 34,  55,  89, 144],

[  1,   2,   3,   4],

[  5,   6,   7,   8],

[  9,  10,  11,  12]])

 

reshape()函式和resize()函式可以重新設定陣列的行數和列數:

 

In [46]: arr5 = np.array(np.arange(24))

In [47]: arr5    #此為一維陣列

Out[47]:

array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,

17, 18, 19, 20, 21, 22, 23])

 

In [48]: a = arr5.reshape(4,6)  

In [49]: a

Out[49]:

array([[ 0,  1,  2,  3,  4,  5],

[ 6,  7,  8,  9, 10, 11],

[12, 13, 14, 15, 16, 17],

[18, 19, 20, 21, 22, 23]])

通過reshape函式將一維陣列設定為二維陣列,且為4行6列的陣列。

 

In [50]: a.resize(6,4)  

In [51]: a

Out[51]:

array([[ 0,  1,  2,  3],

[ 4,  5,  6,  7],

[ 8,  9, 10, 11],

[12, 13, 14, 15],

[16, 17, 18, 19],

[20, 21, 22, 23]])

通過resize函式會直接改變原陣列的形狀。

 

陣列轉換:tolist將陣列轉換為列表,astype()強制轉換陣列的資料型別,下面是兩個函式的例子:

 

In [53]: b = a.tolist()

In [54]: b

Out[54]:

[[0, 1, 2, 3],

[4, 5, 6, 7],

[8, 9, 10, 11],

[12, 13, 14, 15],

[16, 17, 18, 19],

[20, 21, 22, 23]]

In [55]: type(b)

Out[55]: list

 

In [56]: c = a.astype(float)

In [57]: c

Out[57]:

array([[  0.,   1.,   2.,   3.],

[  4.,   5.,   6.,   7.],

[  8.,   9.,  10.,  11.],

[ 12.,  13.,  14.,  15.],

[ 16.,  17.,  18.,  19.],

[ 20.,  21.,  22.,  23.]])

 

In [58]: a.dtype

Out[58]: dtype('int32')

In [59]: c.dtype

Out[59]: dtype('float64')

 

 

陣列元素的獲取

通過索引和切片的方式獲取陣列元素,一維陣列元素的獲取與列表、元組的獲取方式一樣:

In [60]: arr7 = np.array(np.arange(10))

In [61]: arr7

Out[61]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [62]: arr7[3]     #獲取第4個元素

Out[62]: 3

 

In [63]: arr7[:3]    #獲取前3個元素

Out[63]: array([0, 1, 2])

 

In [64]: arr7[3:]    #獲取第4個元素即之後的所有元素

Out[64]: array([3, 4, 5, 6, 7, 8, 9])

 

In [65]: arr7[-2:]   #獲取末尾的2個元素

Out[65]: array([8, 9])

 

In [66]: arr7[::2]   #從第1個元素開始,獲取步長為2的所有元素

Out[66]: array([0, 2, 4, 6, 8])

 

二維陣列元素的獲取:

In [67]: arr8 = np.array(np.arange(12)).reshape(3,4)

In [68]: arr8

Out[68]:

array([[ 0,  1,  2,  3],

[ 4,  5,  6,  7],

[ 8,  9, 10, 11]])

 

In [69]: arr8[1]     #返回陣列的第2行

Out[69]: array([4, 5, 6, 7])

 

In [70]: arr8[:2]    #返回陣列的前2行

Out[70]:

array([[0, 1, 2, 3],

[4, 5, 6, 7]])

 

In [71]: arr8[[0,2]]     #返回指定的第1行和第3行

Out[71]:

array([[ 0,  1,  2,  3],

[ 8,  9, 10, 11]])

 

In [72]: arr8[:,0]  #返回陣列的第1列

Out[72]: array([0, 4, 8])

 

In [73]: arr8[:,-2:]    #返回陣列的後2列

Out[73]:

array([[ 2,  3],

[ 6,  7],

[10, 11]])

 

In [74]: arr8[:,[0,2]]   #返回陣列的第1列和第3列

Out[74]:

array([[ 0,  2],

[ 4,  6],

[ 8, 10]])

 

In [75]: arr8[1,2]   #返回陣列中第2行第3列對應的元素

Out[75]: 6

 

 

布林索引,即索引值為True和False,需要注意的是布林索引必須輸陣列物件。

In [76]: log = np.array([True,False,False,True,True,False])

In [77]: arr9 = np.array(np.arange(24)).reshape(6,4)

In [78]: arr9

Out[78]:

array([[ 0,  1,  2,  3],

[ 4,  5,  6,  7],

[ 8,  9, 10, 11],

[12, 13, 14, 15],

[16, 17, 18, 19],

[20, 21, 22, 23]])

 

In [79]: arr9[log]   #返回所有為True的對應行

Out[79]:

array([[ 0,  1,  2,  3],

[12, 13, 14, 15],

[16, 17, 18, 19]])

 

In [80]: arr9[-log]  #通過負號篩選出所有為False的對應行

Out[80]:

array([[ 4,  5,  6,  7],

[ 8,  9, 10, 11],

[20, 21, 22, 23]])

 

舉一個場景,一維陣列表示區域,二維陣列表示觀測值,如何選取目標區域的觀測?

In [81]: area = np.array(['A','B','A','C','A','B','D'])

In [82]: area

Out[82]:

array(['A', 'B', 'A', 'C', 'A', 'B', 'D'],

dtype='<U1')

 

In [83]: observes = np.array(np.arange(21)).reshape(7,3)

In [84]: observes

Out[84]:

array([[ 0,  1,  2],

[ 3,  4,  5],

[ 6,  7,  8],

[ 9, 10, 11],

[12, 13, 14],

[15, 16, 17],

[18, 19, 20]])

 

In [85]: observes[area == 'A']

Out[85]:

array([[ 0,  1,  2],

[ 6,  7,  8],

[12, 13, 14]])

返回所有A區域的觀測。

 

In [86]: observes[(area == 'A') | (area == 'D')] #條件值需要在&(and),|(or)兩端用圓括號括起來

Out[86]:

array([[ 0,  1,  2],

[ 6,  7,  8],

[12, 13, 14],

[18, 19, 20]])

返回所有A區域和D區域的觀測。

 

當然,布林索引也可以與普通索引或切片混合使用:

In [87]: observes[area == 'A'][:,[0,2]]  

Out[87]:

array([[ 0,  2],

[ 6,  8],

[12, 14]])

返回A區域的所有行,且只獲取第1列與第3列資料。

 

花式索引:實際上就是將陣列作為索引將原陣列的元素提取出來

In [88]: arr10 = np.arange(1,29).reshape(7,4)

In [89]: arr10

Out[89]:

array([[ 1,  2,  3,  4],

[ 5,  6,  7,  8],

[ 9, 10, 11, 12],

[13, 14, 15, 16],

[17, 18, 19, 20],

[21, 22, 23, 24],

[25, 26, 27, 28]])

 

In [90]: arr10[[4,1,3,5]]  #按照指定順序返回指定行

Out[90]:

array([[17, 18, 19, 20],

[ 5,  6,  7,  8],

[13, 14, 15, 16],

[21, 22, 23, 24]])

 

In [91]: arr10[[4,1,5]][:,[0,2,3]] #返回指定的行與列

Out[91]:

array([[17, 19, 20],

[ 5,  7,  8],

[21, 23, 24]])

 

In [92]: arr10[[4,1,5],[0,2,3]]

Out[92]: array([17,  7, 24])

 請注意!這與上面的返回結果是截然不同的,上面返回的是二維陣列,而這條命令返回的是一維陣列。

 

如果想使用比較簡單的方式返回指定行以列的二維陣列的話,可以使用ix_()函式

In [93]: arr10[np.ix_([4,1,5],[0,2,3])]

Out[93]:

array([[17, 19, 20],

[ 5,  7,  8],

[21, 23, 24]])

這與arr10[[4,1,5]][:,[0,2,3]]返回的結果是一致的。

統計函式與線性代數運算

統計運算中常見的聚合函式有:最小值、最大值、中位數、均值、方差、標準差等。首先來看看陣列元素級別的計算

In [94]: arr11 = 5-np.arange(1,13).reshape(4,3)

In [95]: arr12 = np.random.randint(1,10,size = 12).reshape(4,3)

In [96]: arr11

Out[96]:

array([[ 4,  3,  2],

[ 1,  0, -1],

[-2, -3, -4],

[-5, -6, -7]])

 

In [97]: arr12

Out[97]:

array([[1, 3, 7],

[7, 3, 7],

[3, 7, 4],

[6, 1, 2]])

 

In [98]: arr11 ** 2    #計算每個元素的平方

Out[98]:

array([[16,  9,  4],

[ 1,  0,  1],

[ 4,  9, 16],

[25, 36, 49]])

 

In [99]: np.sqrt(arr11)  #計算每個元素的平方根

Out[99]:

array([[ 2.        ,  1.73205081,  1.41421356],

[ 1.        ,  0.        ,         nan],

[        nan,         nan,         nan],

[        nan,         nan,         nan]])

由於負值的平方根沒有意義,故返回nan

 

In [100]: np.exp(arr11)   #計算每個元素的指數值

Out[100]:

array([[  5.45981500e+01,   2.00855369e+01,   7.38905610e+00],

[  2.71828183e+00,   1.00000000e+00,   3.67879441e-01],

[  1.35335283e-01,   4.97870684e-02,   1.83156389e-02],

[  6.73794700e-03,   2.47875218e-03,   9.11881966e-04]])

 

In [101]: np.log(arr12)   #計算每個元素的自然對數值

Out[101]:

array([[ 0.        ,  1.09861229,  1.94591015],

[ 1.94591015,  1.09861229,  1.94591015],

[ 1.09861229,  1.94591015,  1.38629436],

[ 1.79175947,  0.        ,  0.69314718]])

 

In [102]: np.abs(arr11)   #計算每個元素的絕對值

Out[102]:

array([[4, 3, 2],

[1, 0, 1],

[2, 3, 4],

[5, 6, 7]])

 

相同形狀陣列間元素的操作:

In [103]: arr11 + arr12   #加

Out[103]:

array([[ 5,  6,  9],

[ 8,  3,  6],

[ 1,  4,  0],

[ 1, -5, -5]])

 

In [104]: arr11 - arr12   #減

Out[104]:

array([[  3,   0,  -5],

[ -6,  -3,  -8],

[ -5, -10,  -8],

[-11,  -7,  -9]])

 

In [105]: arr11 * arr12   #乘

Out[105]:

array([[  4,   9,  14],

[  7,   0,  -7],

[ -6, -21, -16],

[-30,  -6, -14]])

 

In [106]: arr11 / arr12   #除

Out[106]:

array([[ 4.        ,  1.        ,  0.28571429],

[ 0.14285714,  0.        , -0.14285714],

[-0.66666667, -0.42857143, -1.        ],

[-0.83333333, -6.        , -3.5       ]])

 

In [107]: arr11 // arr12  #整除

Out[107]:

array([[ 4,  1,  0],

[ 0,  0, -1],

[-1, -1, -1],

[-1, -6, -4]], dtype=int32)

In [108]: arr11 % arr12   #取餘

Out[108]:

array([[0, 0, 2],

[1, 0, 6],

[1, 4, 0],

[1, 0, 1]], dtype=int32)

 

接下來我們看看統計運算函式:

In [109]: np.sum(arr11)   #計算所有元素的和

Out[109]: -18

 

In [110]: np.sum(arr11,axis = 0)    #對每一列求和

Out[110]: array([ -2,  -6, -10])

 

In [111]: np.sum(arr11, axis = 1) #對每一行求和

Out[111]: array([  9,   0,  -9, -18])

 

In [112]: np.cumsum(arr11) #對每一個元素求累積和(從上到下,從左到右的元素順序)

Out[112]: array([  4,   7,   9,  10,  10,   9,   7,   4,   0,  -5, -11, -18], dtype=int32)

 

In [113]: np.cumsum(arr11, axis = 0) #計算每一列的累積和,並返回二維陣列

Out[113]:

array([[  4,   3,   2],

[  5,   3,   1],

[  3,   0,  -3],

[ -2,  -6, -10]], dtype=int32)

 

In [114]: np.cumprod(arr11, axis = 1) #計算每一行的累計積,並返回二維陣列

Out[114]:

array([[   4,   12,   24],

[   1,    0,    0],

[  -2,    6,  -24],

[  -5,   30, -210]], dtype=int32)

 

In [115]: np.min(arr11)   #計算所有元素的最小值

Out[115]: -7

 

In [116]: np.max(arr11, axis = 0) #計算每一列的最大值

Out[116]: array([4, 3, 2])

 

In [117]: np.mean(arr11)  #計算所有元素的均值

Out[117]: -1.5

 

In [118]: np.mean(arr11, axis = 1) #計算每一行的均值

Out[118]: array([ 3.,  0., -3., -6.])

 

In [119]: np.median(arr11)   #計算所有元素的中位數

Out[119]: -1.5

 

In [120]: np.median(arr11, axis = 0)   #計算每一列的中位數

Out[120]: array([-0.5, -1.5, -2.5])

 

In [121]: np.var(arr12)   #計算所有元素的方差

Out[121]: 5.354166666666667

 

In [122]: np.std(arr12, axis = 1)   #計算每一行的標準差

Out[122]: array([ 2.49443826,  1.88561808,  1.69967317,  2.1602469 ])

 

numpy中的統計函式運算是非常靈活的,既可以計算所有元素的統計值,也可以計算指定行或列的統計指標。還有其他常用的函式,如符號函式sign,ceil(>=x的最小整數),floor(<=x的最大整數),modf(將浮點數的整數部分與小數部分分別存入兩個獨立的陣列),cos,arccos,sin,arcsin,tan,arctan等。

 

讓我很興奮的一個函式是where(),它類似於Excel中的if函式,可以進行靈活的變換:

 

In [123]: arr11

Out[123]:

array([[ 4,  3,  2],

[ 1,  0, -1],

[-2, -3, -4],

[-5, -6, -7]])

 

In [124]: np.where(arr11 < 0, 'negtive','positive')

Out[124]:

array([['positive', 'positive', 'positive'],

['positive', 'positive', 'negtive'],

['negtive', 'negtive', 'negtive'],

['negtive', 'negtive', 'negtive']],

dtype='<U8')

當然,np.where還可以巢狀使用,完成複雜的運算。

 

 

其它函式

unique(x):計算x的唯一元素,並返回有序結果

intersect(x,y):計算x和y的公共元素,即交集

union1d(x,y):計算x和y的並集

setdiff1d(x,y):計算x和y的差集,即元素在x中,不在y中

setxor1d(x,y):計算集合的對稱差,即存在於一個數組中,但不同時存在於兩個陣列中

in1d(x,y):判斷x的元素是否包含於y中

 

 

線性代數運算

同樣numpu也跟R語言一樣,可以非常方便的進行線性代數方面的計算,如行列式、逆、跡、特徵根、特徵向量等。但需要注意的是,有關線性代數的函式並不在numpy中,而是numpy的子例linalg中。

In [125]: arr13 = np.array([[1,2,3,5],[2,4,1,6],[1,1,4,3],[2,5,4,1]])

In [126]: arr13

Out[126]:

array([[1, 2, 3, 5],

[2, 4, 1, 6],

[1, 1, 4, 3],

[2, 5, 4, 1]])

 

In [127]: np.linalg.det(arr13)    #返回方陣的行列式

Out[127]: 51.000000000000021

 

In [128]: np.linalg.inv(arr13)    #返回方陣的逆

Out[128]:

array([[-2.23529412,  1.05882353,  1.70588235, -0.29411765],

[ 0.68627451, -0.25490196, -0.7254902 ,  0.2745098 ],

[ 0.19607843, -0.21568627,  0.07843137,  0.07843137],

[ 0.25490196,  0.01960784, -0.09803922, -0.09803922]])

 

In [129]: np.trace(arr13) #返回方陣的跡(對角線元素之和),注意跡的求解不在linalg子例程中

Out[129]: 10

 

In [130]: np.linalg.eig(arr13)    #返回由特徵根和特徵向量組成的元組

Out[130]:

(array([ 11.35035004,  -3.99231852,  -0.3732631 ,   3.01523159]),

array([[-0.4754174 , -0.48095078, -0.95004728,  0.19967185],

[-0.60676806, -0.42159999,  0.28426325, -0.67482638],

[-0.36135292, -0.16859677,  0.08708826,  0.70663129],

[-0.52462832,  0.75000995,  0.09497472, -0.07357122]]))

 

In [131]: np.linalg.qr(arr13) #返回方陣的QR分解

Out[131]:

(array([[-0.31622777, -0.07254763, -0.35574573, -0.87645982],

[-0.63245553, -0.14509525,  0.75789308, -0.06741999],

[-0.31622777, -0.79802388, -0.38668014,  0.33709993],

[-0.63245553,  0.580381  , -0.38668014,  0.33709993]]),

array([[-3.16227766, -6.64078309, -5.37587202, -6.95701085],

[ 0.        ,  1.37840488, -1.23330963, -3.04700025],

[ 0.        ,  0.        , -3.40278524,  1.22190924],

[ 0.        ,  0.        ,  0.        , -3.4384193 ]]))

 

In [132]:np.linalg.svd(arr13)    #返回方陣的奇異值分解

Out[132]:

(array([[-0.50908395,  0.27580803,  0.35260559, -0.73514132],

[-0.59475561,  0.4936665 , -0.53555663,  0.34020325],

[-0.39377551, -0.10084917,  0.70979004,  0.57529852],

[-0.48170545, -0.81856751, -0.29162732, -0.11340459]]),

array([ 11.82715609,   4.35052602,   3.17710166,   0.31197297]),

array([[-0.25836994, -0.52417446, -0.47551003, -0.65755329],

[-0.10914615, -0.38326507, -0.54167613,  0.74012294],

[-0.18632462, -0.68784764,  0.69085326,  0.12194478],

[ 0.94160248, -0.32436807, -0.05655931, -0.07050652]]))

 

In [133]: np.dot(arr13,arr13)     #方陣的正真乘積運算

Out[133]:

array([[18, 38, 37, 31],

[23, 51, 38, 43],

[13, 25, 32, 26],

[18, 33, 31, 53]])

 

In [134]:arr14 = np.array([[1,-2,1],[0,2,-8],[-4,5,9]])

In [135]: vector = np.array([0,8,-9])

In [136]: np.linalg.solve(arr14,vector)

Out[136]: array([ 29.,  16.,   3.])

 

 

隨機數生成

統計學中經常會講到資料的分佈特徵,如正態分佈、指數分佈、卡方分佈、二項分佈、泊松分佈等,下面就講講有關分佈的隨機數生成。

正態分佈直方圖

In [137]: import matplotlib #用於繪圖的模組

In [138]: np.random.seed(1234)    #設定隨機種子

In [139]: N = 10000   #隨機產生的樣本量

In [140]: randnorm = np.random.normal(size = N)   #生成正態隨機數

In [141]: counts, bins, path = matplotlib.pylab.hist(randnorm, bins = np.sqrt(N), normed = True, color = 'blue')  #繪製直方圖

以上將直方圖的頻數和組距存放在counts和bins內。

 

In [142]: sigma = 1; mu = 0

In [143]: norm_dist = (1/np.sqrt(2*sigma*np.pi))*np.exp(-((bins-mu)**2)/2)    #正態分佈密度函式

In [144]: matplotlib.pylab.plot(bins,norm_dist,color = 'red') #繪製正態分佈密度函式圖


 

使用二項分佈進行賭博

同時拋棄9枚硬幣,如果正面朝上少於5枚,則輸掉8元,否則就贏8元。如果手中有1000元作為賭資,請問賭博10000次後可能會是什麼情況呢?

In [146]: np.random.seed(1234)

In [147]: binomial = np.random.binomial(9,0.5,10000)  #生成二項分佈隨機數

In [148]: money = np.zeros(10000) #生成10000次賭資的列表

In [149]: money[0] = 1000 #首次賭資為1000元

In [150]: for i in range(1,10000):

     ...:     if binomial[i] < 5:

     ...:         money[i] = money[i-1] - 8  

#如果少於5枚正面,則在上一次賭資的基礎上輸掉8元

     ...:     else:

     ...:         money[i] = money[i-1] + 8  

#如果至少5枚正面,則在上一次賭資的基礎上贏取8元

In [151]: matplotlib.pylab.plot(np.arange(10000), money)


 

使用隨機整數實現隨機遊走

一個醉漢在原始位置上行走10000步後將會在什麼地方呢?如果他每走一步是隨機的,即下一步可能是1也可能是-1。

In [152]: np.random.seed(1234)    #設定隨機種子

In [153]: position = 0    #設定初始位置

In [154]: walk = []   #建立空列表

In [155]: steps = 10000   #假設接下來行走10000步

In [156]: for i in np.arange(steps):

     ...:     step = 1 if np.random.randint(0,2) else -1  #每一步都是隨機的

     ...:     position = position + step  #對每一步進行累計求和

     ...:     walk.append(position)   #確定每一步所在的位置

In [157]: matplotlib.pylab.plot(np.arange(10000), walk)   #繪製隨機遊走圖


 

上面的程式碼還可以寫成(結合前面所講的where函式,cumsum函式):

In [158]: np.random.seed(1234)

In [159]: step = np.where(np.random.randint(0,2,10000)>0,1,-1)

In [160]: position = np.cumsum(step)

In [161]: matplotlib.pylab.plot(np.arange(10000), position)

 


避免for迴圈,可以達到同樣的效果。