數(shù)據(jù)分析 2
NumPy: 數(shù)組和?矢量量計(jì)算
NumPy之于數(shù)值計(jì)算特別重要的原因之?一,是因?yàn)樗梢?高效處理理?大數(shù)組的數(shù)據(jù)。
NumPy是在?一個(gè)連續(xù)的內(nèi)存塊中存儲(chǔ)數(shù)據(jù),獨(dú)?立于其他Python內(nèi)置對(duì)象。NumPy的C語(yǔ)?言編
寫的算法庫(kù)可以操作內(nèi)存,?而不不必進(jìn)?行行類型檢查或其它前期?工作。?比起Python的內(nèi)置序列列,
NumPy數(shù)組使?用的內(nèi)存更更少。
NumPy可以在整個(gè)數(shù)組上執(zhí)?行行復(fù)雜的計(jì)算,?而不不需要Python的for循環(huán)。
性能對(duì)?比
基于NumPy的算法要?比純Python快10到100倍(甚?至更更快),并且使?用的內(nèi)存更更少。
In [7]: import numpy as np
In [8]: %timeit my_arr = np.arange(1000000)
In [9]: %timeit my_list = list(range(1000000))
NumPy的ndarray:?一種多維數(shù)組對(duì)象
NumPy最重要的?一個(gè)特點(diǎn)就是其N維數(shù)組對(duì)象(即ndarray), 該對(duì)象是?一個(gè)快速?而靈活的?大
數(shù)據(jù)集容器?。你可以利利?用這種數(shù)組對(duì)整塊數(shù)據(jù)執(zhí)?行行?一些數(shù)學(xué)運(yùn)算,其語(yǔ)法跟標(biāo)量量元素之間的運(yùn)
算?一樣。
In [12]: import numpy as np
In [13]: data = np.random.randn(2, 3)
In [14]: data
Out[14]:
array([[-0.2047, 0.4789, -0.5194],
[-0.5557, 1.9658, 1.3934]])
In [15]: data * 10
Out[15]:
array([[ -2.0471, 4.7894, -5.1944],
[ -5.5573, 19.6578, 13.9341]])
In [16]: data + data
Out[16]:
array([[-0.4094, 0.9579, -1.0389],
[-1.1115, 3.9316, 2.7868]])
ndarray是?一個(gè)通?用的同構(gòu)數(shù)據(jù)多維容器?,所有元素必須是相同類型的
取維度大小
data.shape
取數(shù)據(jù)數(shù)據(jù)類型
data.dtype
創(chuàng)建ndarray
In [19]: data1 = [6, 7.5, 8, 0, 1]
In [20]: arr1 = np.array(data1)
In [21]: arr1
Out[21]: array([ 6. , 7.5, 8. , 0. , 1. ])
嵌套序列列(?比如由?一組等?長(zhǎng)列列表組成的列列表)將會(huì)被轉(zhuǎn)換為一個(gè)多維數(shù)組
In [22]: data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
In [23]: arr2 = np.array(data2)
In [24]: arr2
Out[24]:
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
取維度
arr2.ndim
arr2.shape
arr2.dtype
zeros和ones分別可以創(chuàng)建指定?長(zhǎng)度或形狀的全0或全1數(shù)組。empty可以創(chuàng)建一個(gè)沒(méi)有任何具
體值的數(shù)組
In [29]: np.zeros(10)
Out[29]: array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
In [30]: np.zeros((3, 6))
Out[30]:
array([[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0.]])
In [31]: np.empty((2, 3, 2))
np.ones(10)
np.empty返回的都是?一些未初始化的垃圾值
In [32]: np.arange(15)
Out[32]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

ndarray的數(shù)據(jù)類型
In [33]: arr1 = np.array([1, 2, 3], dtype=np.float64)
In [34]: arr2 = np.array([1, 2, 3], dtype=np.int32)
In [35]: arr1.dtype
Out[35]: dtype('float64')
In [36]: arr2.dtype
Out[36]: dtype('int32')
astype?方法明確地將?一個(gè)數(shù)組從?一個(gè)dtype轉(zhuǎn)換成另?一個(gè)dtype
In [37]: arr = np.array([1, 2, 3, 4, 5])
In [38]: arr.dtype
Out[38]: dtype('int64')
In [39]: float_arr = arr.astype(np.float64)
In [40]: float_arr.dtype
Out[40]: dtype('float64')
將浮點(diǎn)數(shù)轉(zhuǎn)換成整數(shù),則?小數(shù)部分將會(huì)被截取刪除
In [41]: arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
In [42]: arr
Out[42]: array([ 3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
In [43]: arr.astype(np.int32)
Out[43]: array([ 3, -1, -2, 0, 12, 10], dtype=int32)
調(diào)?用astype總會(huì)創(chuàng)建?一個(gè)新的數(shù)組(?一個(gè)數(shù)據(jù)的備份)
NumPy數(shù)組的運(yùn)算
不不?用編寫循環(huán)即可對(duì)數(shù)據(jù)執(zhí)?行行批量量運(yùn)算。NumPy?用戶稱其為?矢量量化(vectorization)。?大?小相
等的數(shù)組之間的任何算術(shù)運(yùn)算都會(huì)將運(yùn)算應(yīng)?用到元素級(jí)
In [51]: arr = np.array([[1., 2., 3.], [4., 5., 6.]])
In [52]: arr
Out[52]:
array([[ 1., 2., 3.],
[ 4., 5., 6.]])
In [53]: arr * arr
Out[53]:
array([[ 1., 4., 9.],
[ 16., 25., 36.]])
In [54]: arr - arr
Out[54]:
array([[ 0., 0., 0.],
[ 0., 0., 0.]])
數(shù)組與標(biāo)量量的算術(shù)運(yùn)算會(huì)將標(biāo)量量值傳播到各個(gè)元素
In [55]: 1 / arr
Out[55]:
array([[ 1. , 0.5 , 0.3333],
[ 0.25 , 0.2 , 0.1667]])
In [56]: arr * 0.5
?大?小相同的數(shù)組之間的?比較會(huì)?生成布爾值數(shù)組
In [57]: arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
In [58]: arr2
Out[58]:
array([[ 0., 4., 1.],
[ 7., 2., 12.]])
In [59]: arr2 > arr
Out[59]:
array([[False, True, False],
[ True, False, True]], dtype=bool)
基本的索引和切?片
In [60]: arr = np.arange(10)
In [61]: arr
Out[61]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [62]: arr[5]
Out[62]: 5
In [63]: arr[5:8]
Out[63]: array([5, 6, 7])
In [64]: arr[5:8] = 12
In [65]: arr
Out[65]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
In [66]: arr_slice = arr[5:8]
In [67]: arr_slice
Out[67]: array([12, 12, 12])
In [68]: arr_slice[1] = 12345
In [69]: arr
Out[69]: array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8,
9])
切?片[ : ]會(huì)給數(shù)組中的所有值賦值
In [70]: arr_slice[:] = 64
In [71]: arr
Out[71]: array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])
ndarray切?片的?一份副本?而?非視圖,就需要明確地進(jìn)?行行復(fù)制操作,例例如arr[5:8].copy()
In [72]: arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
In [73]: arr2d[2]
Out[73]: array([7, 8, 9])
兩種方式一樣
In [74]: arr2d[0][2]
Out[74]: 3
In [75]: arr2d[0, 2]
Out[75]: 3
多維數(shù)組中,如果省略略了了后?面的索引,則返回對(duì)象會(huì)是?一個(gè)維度低?一點(diǎn)的ndarray
In [76]: arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
In [77]: arr3d
Out[77]:
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
arr3d.ndim
In [78]: arr3d[0]
Out[78]:
array([[1, 2, 3],
[4, 5, 6]])
arr3d[0].ndim
標(biāo)量量值和數(shù)組都可以被賦值給arr3d[0]
In [79]: old_values = arr3d[0].copy()
In [80]: arr3d[0] = 42
In [81]: arr3d
Out[81]:
array([[[42, 42, 42],
[42, 42, 42]],
[[ 7, 8, 9],
[10, 11, 12]]])
In [82]: arr3d[0] = old_values
In [83]: arr3d
Out[83]:
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
In [84]: arr3d[1, 0]
Out[84]: array([7, 8, 9])
切?片索引
In [90]: arr2d
Out[90]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [91]: arr2d[:2]
Out[91]:
array([[1, 2, 3],
[4, 5, 6]])
?一次傳?入多個(gè)切?片
In [92]: arr2d[:2, 1:]
Out[92]:
array([[2, 3],
[5, 6]])
將整數(shù)索引和切?片混合
選取第?二?行行的前兩列列
In [93]: arr2d[1, :2]
Out[93]: array([4, 5])
選擇第三列列的前兩行行
In [94]: arr2d[:2, 2]
Out[94]: array([3, 6])
“只有冒號(hào)”表示選取整個(gè)軸
In [95]: arr2d[:, :1]
Out[95]:
array([[1],
[4],
[7]])
In [96]: arr2d[:2, 1:] = 0
In [97]: arr2d
Out[97]:
array([[1, 0, 0],
[4, 0, 0],
[7, 8, 9]])
布爾型索引
假設(shè)我們有?一個(gè)?用于存儲(chǔ)數(shù)據(jù)的數(shù)組以及?一個(gè)存儲(chǔ)姓名的數(shù)組(含有重復(fù)項(xiàng))
In [98]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
In [99]: data = np.random.randn(7, 4)
In [100]: names
Out[100]:
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'],
dtype='<U4')
In [101]: data
Out[101]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.0072, -1.2962, 0.275 , 0.2289],
[ 1.3529, 0.8864, -2.0016, -0.3718],
[ 1.669 , -0.4386, -0.5397, 0.477 ],
[ 3.2489, -1.0212, -0.5771, 0.1241],
[ 0.3026, 0.5238, 0.0009, 1.3438],
[-0.7135, -0.8312, -2.3702, -1.8608]])
In [102]: names == 'Bob'
Out[102]: array([ True, False, False, True, False, False, False], dtype=bool)
In [103]: data[names == 'Bob']
Out[103]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.669 , -0.4386, -0.5397, 0.477 ]])
In [104]: data[names == 'Bob', 2:]
Out[104]:
array([[ 0.769 , 1.2464],
[-0.5397, 0.477 ]])
In [105]: data[names == 'Bob', 3]
Out[105]: array([ 1.2464, 0.477 ])
要選擇除”bob”以外的其他值,既可以使?用不不等于符號(hào)(!=),也可以通過(guò)~對(duì)條件進(jìn)?行行否定
In [106]: names != 'Bob'
Out[106]: array([False, True, True, False, True, True, True], dtype=bool)
In [107]: data[~(names == 'Bob')]
Out[107]:
array([[ 1.0072, -1.2962, 0.275 , 0.2289],
[ 1.3529, 0.8864, -2.0016, -0.3718],
[ 3.2489, -1.0212, -0.5771, 0.1241],
[ 0.3026, 0.5238, 0.0009, 1.3438],
[-0.7135, -0.8312, -2.3702, -1.8608]])
In [110]: mask = (names == 'Bob') | (names == 'Will')
In [111]: mask
Out[111]: array([ True, False, True, True, True, False, False], dtype=bool)
In [112]: data[mask]
Out[112]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.3529, 0.8864, -2.0016, -0.3718],
[ 1.669 , -0.4386, -0.5397, 0.477 ],
[ 3.2489, -1.0212, -0.5771, 0.1241]])
In [113]: data[data < 0] = 0
In [114]: data
Out[114]:
array([[ 0.0929, 0.2817, 0.769 , 1.2464],
[ 1.0072, 0. , 0.275 , 0.2289],
[ 1.3529, 0.8864, 0. , 0. ],
[ 1.669 , 0. , 0. , 0.477 ],
[ 3.2489, 0. , 0. , 0.1241],
[ 0.3026, 0.5238, 0.0009, 1.3438],
[ 0. , 0. , 0. , 0. ]])
In [115]: data[names != 'Joe'] = 7
In [116]: data
Out[116]:
array([[ 7. , 7. , 7. , 7. ],
[ 1.0072, 0. , 0.275 , 0.2289],
[ 7. , 7. , 7. , 7. ],
[ 7. , 7. , 7. , 7. ],
[ 7. , 7. , 7. , 7. ],
[ 0.3026, 0.5238, 0.0009, 1.3438],
[ 0. , 0. , 0. , 0. ]])
花式索引
花式索引(Fancy indexing)是一個(gè)NumPy術(shù)語(yǔ),它指的是利利?用整數(shù)數(shù)組進(jìn)?行行索引
In [117]: arr = np.empty((8, 4))
In [118]: for i in range(8):
.....: arr[i] = i
In [119]: arr
Out[119]:
array([[ 0., 0., 0., 0.],
[ 1., 1., 1., 1.],
[ 2., 2., 2., 2.],
[ 3., 3., 3., 3.],
[ 4., 4., 4., 4.],
[ 5., 5., 5., 5.],
[ 6., 6., 6., 6.],
[ 7., 7., 7., 7.]])
為了了以特定順序選取?行行?子集,只需傳?入?一個(gè)?用于指定順序的整數(shù)列列表或ndarray即可
In [120]: arr[[4, 3, 0, 6]]
Out[120]:
array([[ 4., 4., 4., 4.],
[ 3., 3., 3., 3.],
[ 0., 0., 0., 0.],
[ 6., 6., 6., 6.]])
使?用負(fù)數(shù)索引將會(huì)從末尾開(kāi)始選取?行行
In [121]: arr[[-3, -5, -7]]
Out[121]:
array([[ 5., 5., 5., 5.],
[ 3., 3., 3., 3.],
[ 1., 1., 1., 1.]])
?一次傳?入多個(gè)索引數(shù)組會(huì)有?一點(diǎn)特別。它返回的是?一個(gè)?一維數(shù)組,其中的元素對(duì)應(yīng)各個(gè)索引元
組
In [122]: arr = np.arange(32).reshape((8, 4))
In [123]: arr
Out[123]:
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],
[24, 25, 26, 27],
[28, 29, 30, 31]])
最終選出的是元素(1,0)、(5,3)、(7,1)和(2,2)
In [124]: arr[[1, 5, 7, 2], [0, 3, 1, 2]]
Out[124]: array([ 4, 23, 29, 10])
In [125]: arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]
Out[125]:
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
數(shù)組轉(zhuǎn)置和軸對(duì)換
轉(zhuǎn)置是重塑的?一種特殊形式,它返回的是源數(shù)據(jù)的視圖(不不會(huì)進(jìn)?行行任何復(fù)制操作)
In [126]: arr = np.arange(15).reshape((3, 5))
In [127]: arr
Out[127]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
In [128]: arr.T
Out[128]:
array([[ 0, 5, 10],
[ 1, 6, 11],
[ 2, 7, 12],
[ 3, 8, 13],
[ 4, 9, 14]])
利利?用np.dot計(jì)算矩陣內(nèi)積
In [129]: arr = np.random.randn(6, 3)
In [130]: arr
Out[130]:
array([[-0.8608, 0.5601, -1.2659],
[ 0.1198, -1.0635, 0.3329],
[-2.3594, -0.1995, -1.542 ],
[-0.9707, -1.307 , 0.2863],
[ 0.378 , -0.7539, 0.3313],
[ 1.3497, 0.0699, 0.2467]])
In [131]: np.dot(arr.T, arr)
Out[131]:
array([[ 9.2291, 0.9394, 4.948 ],
[ 0.9394, 3.7662, -1.3622],
[ 4.948 , -1.3622, 4.3437]])
對(duì)于?高維數(shù)組,transpose需要得到?一個(gè)由軸編號(hào)組成的元組才能對(duì)這些軸進(jìn)?行行轉(zhuǎn)置
In [132]: arr = np.arange(16).reshape((2, 2, 4))
In [133]: arr
Out[133]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [134]: arr.transpose((1, 0, 2))
Out[134]:
array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[12, 13, 14, 15]]])
In [135]: arr
Out[135]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [136]: arr.swapaxes(1, 2)
Out[136]:
array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]],
[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])
arr.swapaxes(0, 1)
通?用函數(shù)(ufunc):快速的元素級(jí)數(shù)組函數(shù)
In [137]: arr = np.arange(10)
In [138]: arr
Out[138]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [139]: np.sqrt(arr)
Out[139]:
array([ 0. , 1. , 1.4142, 1.7321, 2. , 2.2361, 2.4495,
2.6458, 2.8284, 3. ])
In [140]: np.exp(arr)
Out[140]:
array([ 1. , 2.7183, 7.3891, 20.0855, 54.5982,
148.4132, 403.4288, 1096.6332, 2980.958 , 8103.0839])
add或maximum接受2個(gè)數(shù)組(因此也叫?二元(binary)ufunc),并返回?一個(gè)結(jié)果數(shù)組
In [141]: x = np.random.randn(8)
In [142]: y = np.random.randn(8)
In [143]: x
Out[143]:
array([-0.0119, 1.0048, 1.3272, -0.9193, -1.5491, 0.0222, 0.7584,
-0.6605])
In [144]: y
Out[144]:
array([ 0.8626, -0.01 , 0.05 , 0.6702, 0.853 , -0.9559, -0.0235,
-2.3042])
In [145]: np.maximum(x, y)
Out[145]:
array([ 0.8626, 1.0048, 1.3272, 0.6702, 0.853 , 0.0222, 0.7584,
-0.6605])
返回浮點(diǎn)數(shù)數(shù)組的小數(shù)和整數(shù)部分
In [146]: arr = np.random.randn(7) * 5
In [147]: arr
Out[147]: array([-3.2623, -6.0915, -6.663 , 5.3731, 3.6182, 3.45 ,
5.0077])
In [148]: remainder, whole_part = np.modf(arr)
In [149]: remainder
Out[149]: array([-0.2623, -0.0915, -0.663 , 0.3731,
0.6182, 0.45 , 0.0077])
In [150]: whole_part
Out[150]: array([-3., -6., -6., 5., 3., 3., 5.])
利利用數(shù)組進(jìn)行行數(shù)據(jù)處理理
?用數(shù)組表達(dá)式代替循環(huán)的做法,通常被稱為?矢量量化。?一般來(lái)說(shuō),?矢量量化數(shù)組運(yùn)算要?比等價(jià)的純
Python?方式快上?一兩個(gè)數(shù)量量級(jí)(甚?至更更多)。
假設(shè)我們想要在?一組值(?網(wǎng)格型)上計(jì)算函數(shù)sqrt(x2+y2)
np.meshgrid函數(shù)接受兩個(gè)?一維數(shù)組,并產(chǎn)?生兩個(gè)?二維矩陣(對(duì)應(yīng)于兩個(gè)數(shù)組中所有的(x,y)
對(duì))
In [155]: points = np.arange(-5, 5, 0.01) # 1000 equally spaced points
In [156]: xs, ys = np.meshgrid(points, points)
In [157]: ys
Out[157]:
array([[-5. , -5. , -5. , ..., -5. , -5. , -5. ],
[-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],
[-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],
...,
[ 4.97, 4.97, 4.97, ..., 4.97, 4.97, 4.97],
[ 4.98, 4.98, 4.98, ..., 4.98, 4.98, 4.98],
[ 4.99, 4.99, 4.99, ..., 4.99, 4.99, 4.99]])
In [158]: z = np.sqrt(xs ** 2 + ys ** 2)
In [159]: z
Out[159]:
array([[ 7.0711, 7.064 , 7.0569, ..., 7.0499, 7.0569, 7.064 ],
[ 7.064 , 7.0569, 7.0499, ..., 7.0428, 7.0499, 7.0569],
[ 7.0569, 7.0499, 7.0428, ..., 7.0357, 7.0428, 7.0499],
...,
[ 7.0499, 7.0428, 7.0357, ..., 7.0286, 7.0357, 7.0428],
[ 7.0569, 7.0499, 7.0428, ..., 7.0357, 7.0428, 7.0499],
[ 7.064 , 7.0569, 7.0499, ..., 7.0428, 7.0499, 7.0569]])
matplotlib創(chuàng)建了了這個(gè)?二維數(shù)組的可視化
In [160]: import matplotlib.pyplot as plt
In [161]: plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()
Out[161]: <matplotlib.colorbar.Colorbar at 0x7f715e3fa630>
In [162]: plt.title("Image plot of for a grid of values")
Out[162]: <matplotlib.text.Text at 0x7f715d2de748>
plt.show()
將條件邏輯表述為數(shù)組運(yùn)算
In [165]: xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
In [166]: yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
In [167]: cond = np.array([True, False, True, True, False])
當(dāng)cond中的值為True時(shí),選取xarr的值,否則從yarr中選取
In [170]: result = np.where(cond, xarr, yarr)
In [171]: result
Out[171]: array([ 1.1, 2.2, 1.3, 1.4, 2.5])
假設(shè)有?一個(gè)由隨機(jī)數(shù)據(jù)組成的矩陣,你希望將所有正值替換為2,將所有負(fù)值替換為-2
In [172]: arr = np.random.randn(4, 4)
In [173]: arr
Out[173]:
array([[-0.5031, -0.6223, -0.9212, -0.7262],
[ 0.2229, 0.0513, -1.1577, 0.8167],
[ 0.4336, 1.0107, 1.8249, -0.9975],
[ 0.8506, -0.1316, 0.9124, 0.1882]])
In [174]: arr > 0
Out[174]:
array([[False, False, False, False],
[ True, True, False, True],
[ True, True, True, False],
[ True, False, True, True]], dtype=bool)
In [175]: np.where(arr > 0, 2, -2)
Out[175]:
array([[-2, -2, -2, -2],
[ 2, 2, -2, 2],
[ 2, 2, 2, -2],
[ 2, -2, 2, 2]])
用常數(shù)2替換arr中所有正的值
In [176]: np.where(arr > 0, 2, arr)
Out[176]:
array([[-0.5031, -0.6223, -0.9212, -0.7262],
[ 2. , 2. , -1.1577, 2. ],
[ 2. , 2. , 2. , -0.9975],
[ 2. , -0.1316, 2. , 2. ]])
數(shù)學(xué)和統(tǒng)計(jì)?方法
可以通過(guò)數(shù)組上的?一組數(shù)學(xué)函數(shù)對(duì)整個(gè)數(shù)組或某個(gè)軸向的數(shù)據(jù)進(jìn)?行行統(tǒng)計(jì)計(jì)算。sum、mean以
及標(biāo)準(zhǔn)差std等聚合計(jì)算(aggregation,通常叫做約簡(jiǎn)(reduction))
In [177]: arr = np.random.randn(5, 4)
In [178]: arr
Out[178]:
array([[ 2.1695, -0.1149, 2.0037, 0.0296],
[ 0.7953, 0.1181, -0.7485, 0.585 ],
[ 0.1527, -1.5657, -0.5625, -0.0327],
[-0.929 , -0.4826, -0.0363, 1.0954],
[ 0.9809, -0.5895, 1.5817, -0.5287]])
In [179]: arr.mean()
Out[179]: 0.19607051119998253
In [180]: np.mean(arr)
Out[180]: 0.19607051119998253
In [181]: arr.sum()
Out[181]: 3.9214102239996507
arr.mean(1)是“計(jì)算?行行的平均值”,arr.sum(0)是“計(jì)算每列列的和”
In [182]: arr.mean(axis=1)
Out[182]: array([ 1.022 , 0.1875, -0.502 , -0.0881, 0.3611])
In [183]: arr.sum(axis=0)
Out[183]: array([ 3.1693, -2.6345, 2.2381, 1.1486])
In [184]: arr = np.array([0, 1, 2, 3, 4, 5, 6, 7])
In [185]: arr.cumsum()
Out[185]: array([ 0, 1, 3, 6, 10, 15, 21, 28])
In [186]: arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
In [187]: arr
Out[187]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
所有元素的累積和
In [188]: arr.cumsum(axis=0)
Out[188]:
array([[ 0, 1, 2],
[ 3, 5, 7],
[ 9, 12, 15]])
所有元素的累積積
In [189]: arr.cumprod(axis=1)
Out[189]:
array([[ 0, 0, 0],
[ 3, 12, 60],
[ 6, 42, 336]])
?用于布爾型數(shù)組的?方法
In [190]: arr = np.random.randn(100)
In [191]: (arr > 0).sum()
Out[191]: 42
any?用于測(cè)試數(shù)組中是否存在?一個(gè)或多個(gè)True,?而all則檢查數(shù)組中所有值是否都是True, 這兩個(gè)
?方法也能?用于?非布爾型數(shù)組,所有?非0元素將會(huì)被當(dāng)做True
In [192]: bools = np.array([False, False, True, False])
In [193]: bools.any()
Out[193]: True
In [194]: bools.all()
Out[194]: False
排序
In [195]: arr = np.random.randn(6)
In [196]: arr
Out[196]: array([ 0.6095, -0.4938, 1.24 , -0.1357, 1.43 , -0.8469])
In [197]: arr.sort()
In [198]: arr
Out[198]: array([-0.8469, -0.4938, -0.1357, 0.6095, 1.24 , 1.43 ])
多維數(shù)組可以在任何?一個(gè)軸向上進(jìn)?行行排序
In [199]: arr = np.random.randn(5, 3)
In [200]: arr
Out[200]:
array([[ 0.6033, 1.2636, -0.2555],
[-0.4457, 0.4684, -0.9616],
[-1.8245, 0.6254, 1.0229],
[ 1.1074, 0.0909, -0.3501],
[ 0.218 , -0.8948, -1.7415]])
In [201]: arr.sort(1)
In [202]: arr
Out[202]:
array([[-0.2555, 0.6033, 1.2636],
[-0.9616, -0.4457, 0.4684],
[-1.8245, 0.6254, 1.0229],
[-0.3501, 0.0909, 1.1074],
[-1.7415, -0.8948, 0.218 ]])
頂級(jí)?方法np.sort返回的是數(shù)組的已排序副本,?而就地排序則會(huì)修改數(shù)組本身
唯?一化以及其它的集合邏輯
找出數(shù)組中的唯?一值并返回已排序的結(jié)果
In [206]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
In [207]: np.unique(names)
Out[207]:
array(['Bob', 'Joe', 'Will'],
dtype='<U4')
In [208]: ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])
In [209]: np.unique(ints)
Out[209]: array([1, 2, 3, 4])
函數(shù)np.in1d?用于測(cè)試?一個(gè)數(shù)組中的值在另?一個(gè)數(shù)組中的成員資格,返回?一個(gè)布爾型數(shù)組
In [211]: values = np.array([6, 0, 0, 3, 2, 5, 6])
In [212]: np.in1d(values, [2, 3, 6])
Out[212]: array([ True, False, False, True, True, False, True], dtype=bool)
?用于數(shù)組的?文件輸?入輸出

NumPy的內(nèi)置?二進(jìn)制格式讀寫
np.save和np.load是讀寫磁盤數(shù)組數(shù)據(jù)的兩個(gè)主要函數(shù)。默認(rèn)情況下,數(shù)組是以未壓縮的原始
?二進(jìn)制格式保存在擴(kuò)展名為.npy的?文件中的
In [213]: arr = np.arange(10)
In [214]: np.save('some_array', arr)
In [215]: np.load('some_array.npy')
Out[215]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
通過(guò)np.savez可以將多個(gè)數(shù)組保存到?一個(gè)未壓縮?文件中
In [216]: np.savez('array_archive.npz', a=arr, b=arr)
In [217]: arch = np.load('array_archive.npz')
In [218]: arch['b']
Out[218]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
將數(shù)據(jù)壓縮,可以使?用numpy.savez_compressed
In [219]: np.savez_compressed('arrays_compressed.npz', a=arr, b=arr)
線性代數(shù)
矩陣乘法的dot函數(shù)
In [223]: x = np.array([[1., 2., 3.], [4., 5., 6.]])
In [224]: y = np.array([[6., 23.], [-1, 7], [8, 9]])
In [225]: x
Out[225]:
array([[ 1., 2., 3.],
[ 4., 5., 6.]])
In [226]: y
Out[226]:
array([[ 6., 23.],
[ -1., 7.],
[ 8., 9.]])
In [227]: x.dot(y)
Out[227]:
array([[ 28., 64.],
[ 67., 181.]])
?一個(gè)?二維數(shù)組跟?一個(gè)?大?小合適的?一維數(shù)組的矩陣點(diǎn)積運(yùn)算之后將會(huì)得到?一個(gè)?一維數(shù)組
In [229]: np.dot(x, np.ones(3))
Out[229]: array([ 6., 15.])
@符也可以?用作中綴運(yùn)算符,進(jìn)?行行矩陣乘法
In [230]: x @ np.ones(3)
Out[230]: array([ 6., 15.])
偽隨機(jī)數(shù)?生成
?用normal來(lái)得到?一個(gè)標(biāo)準(zhǔn)正態(tài)分布的4×4樣本數(shù)組
In [238]: samples = np.random.normal(size=(4, 4))
In [239]: samples
Out[239]:
array([[ 0.5732, 0.1933, 0.4429, 1.2796],
[ 0.575 , 0.4339, -0.7658, -1.237 ],
[-0.5367, 1.8545, -0.92 , -0.1082],
[ 0.1525, 0.9435, -1.0953, -0.144 ]])
Python內(nèi)置的random模塊則只能?一次?生成?一個(gè)樣本值。從下?面的測(cè)試結(jié)果中可以看出,如果
需要產(chǎn)?生?大量量樣本值,numpy.random快了了不不?止?一個(gè)數(shù)量量級(jí)
In [240]: from random import normalvariate
In [241]: N = 1000000
In [242]: %timeit samples = [normalvariate(0, 1) for _ in range(N)]
1.77 s +- 126 ms per loop (mean +- std. dev. of 7 runs, 1 loop each)
In [243]: %timeit np.random.normal(size=N)
61.7 ms +- 1.32 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)
numpy.random的數(shù)據(jù)?生成函數(shù)使?用了了全局的隨機(jī)種?子。要避免全局狀態(tài),你可以使?用
numpy.random.RandomState,創(chuàng)建?一個(gè)與其它隔離的隨機(jī)數(shù)?生成器?
In [245]: rng = np.random.RandomState(1234)
In [246]: rng.randn(10)
Out[246]:
array([ 0.4714, -1.191 , 1.4327, -0.3127, -0.7206, 0.8872, 0.8596,
-0.6365, 0.0157, -2.2427])

示例例:隨機(jī)漫步
用np.random模塊一次性隨機(jī)產(chǎn)生1000個(gè)“擲硬幣”結(jié)果(即兩個(gè)數(shù)中任選一個(gè)),將其分別設(shè)
置為1或-1,然后計(jì)算累計(jì)和
In [251]: nsteps = 1000
In [252]: draws = np.random.randint(0, 2, size=nsteps)
In [253]: steps = np.where(draws > 0, 1, -1)
In [254]: walk = steps.cumsum()
In [255]: walk.min()
Out[255]: -3
In [256]: walk.max()
Out[256]: 31
我們想要知道本次隨機(jī)漫步需要多久才能距離初始0點(diǎn)至少10步遠(yuǎn)(任一方向均可)
In [257]: (np.abs(walk) >= 10).argmax()
Out[257]: 37