python输入一个数组输出24进制式的时间_【翻译】《利用Python进行数据分析·第2版》第4章(下)NumPy基础:数组和矢量计算...
前文傳送門:
4.3 利用數(shù)組進(jìn)行數(shù)據(jù)處理
NumPy數(shù)組使你可以將許多種數(shù)據(jù)處理任務(wù)表述為簡(jiǎn)潔的數(shù)組表達(dá)式(否則需要編寫循環(huán))。用數(shù)組表達(dá)式代替循環(huán)的做法,通常被稱為矢量化。一般來(lái)說(shuō),矢量化數(shù)組運(yùn)算要比等價(jià)的純Python方式快上一兩個(gè)數(shù)量級(jí)(甚至更多),尤其是各種數(shù)值計(jì)算。在后面內(nèi)容中(見附錄A)我將介紹廣播,這是一種針對(duì)矢量化計(jì)算的強(qiáng)大手段。
作為簡(jiǎn)單的例子,假設(shè)我們想要在一組值(網(wǎng)格型)上計(jì)算函數(shù)sqrt(x^2+y^2)。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]])
現(xiàn)在,對(duì)該函數(shù)的求值運(yùn)算就好辦了,把這兩個(gè)數(shù)組當(dāng)做兩個(gè)浮點(diǎn)數(shù)那樣編寫表達(dá)式即可:
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]])
作為第9章的先導(dǎo),我用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]:
In [162]: plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")
Out[162]:
見圖4-3。這張圖是用matplotlib的imshow函數(shù)創(chuàng)建的。
圖4-3 根據(jù)網(wǎng)格對(duì)函數(shù)求值的結(jié)果
將條件邏輯表述為數(shù)組運(yùn)算
numpy.where函數(shù)是三元表達(dá)式x if condition else y的矢量化版本。假設(shè)我們有一個(gè)布爾數(shù)組和兩個(gè)值數(shù)組:
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])
假設(shè)我們想要根據(jù)cond中的值選取xarr和yarr的值:當(dāng)cond中的值為True時(shí),選取xarr的值,否則從yarr中選取。列表推導(dǎo)式的寫法應(yīng)該如下所示:
In [168]: result = [(x if c else y)
.....: for x, y, c in zip(xarr, yarr, cond)]
In [169]: result
Out[169]: [1.1000000000000001, 2.2000000000000002, 1.3, 1.3999999999999999, 2.5]
這有幾個(gè)問(wèn)題。第一,它對(duì)大數(shù)組的處理速度不是很快(因?yàn)樗泄ぷ鞫际怯杉働ython完成的)。第二,無(wú)法用于多維數(shù)組。若使用np.where,則可以將該功能寫得非常簡(jiǎn)潔:
In [170]: result = np.where(cond, xarr, yarr)
In [171]: result
Out[171]: array([ 1.1, 2.2, 1.3, 1.4, 2.5])
np.where的第二個(gè)和第三個(gè)參數(shù)不必是數(shù)組,它們都可以是標(biāo)量值。在數(shù)據(jù)分析工作中,where通常用于根據(jù)另一個(gè)數(shù)組而產(chǎn)生一個(gè)新的數(shù)組。假設(shè)有一個(gè)由隨機(jī)數(shù)據(jù)組成的矩陣,你希望將所有正值替換為2,將所有負(fù)值替換為-2。若利用np.where,則會(huì)非常簡(jiǎn)單:
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]])
使用np.where,可以將標(biāo)量和數(shù)組結(jié)合起來(lái)。例如,我可用常數(shù)2替換arr中所有正的值:
In [176]: np.where(arr > 0, 2, arr) # set only positive values to 2
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. ]])
傳遞給where的數(shù)組大小可以不相等,甚至可以是標(biāo)量值。
數(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))既可以當(dāng)做數(shù)組的實(shí)例方法調(diào)用,也可以當(dāng)做頂級(jí)NumPy函數(shù)使用。
這里,我生成了一些正態(tài)分布隨機(jī)數(shù)據(jù),然后做了聚類統(tǒng)計(jì):
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
mean和sum這類的函數(shù)可以接受一個(gè)axis選項(xiàng)參數(shù),用于計(jì)算該軸向上的統(tǒng)計(jì)值,最終結(jié)果是一個(gè)少一維的數(shù)組:
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])
這里,arr.mean(1)是“計(jì)算行的平均值”,arr.sum(0)是“計(jì)算每列的和”。
其他如cumsum和cumprod之類的方法則不聚合,而是產(chǎn)生一個(gè)由中間結(jié)果組成的數(shù)組:
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])
在多維數(shù)組中,累加函數(shù)(如cumsum)返回的是同樣大小的數(shù)組,但是會(huì)根據(jù)每個(gè)低維的切片沿著標(biāo)記軸計(jì)算部分聚類:
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]])
表4-5列出了全部的基本數(shù)組統(tǒng)計(jì)方法。后續(xù)章節(jié)中有很多例子都會(huì)用到這些方法。
用于布爾型數(shù)組的方法
在上面這些方法中,布爾值會(huì)被強(qiáng)制轉(zhuǎn)換為1(True)和0(False)。因此,sum經(jīng)常被用來(lái)對(duì)布爾型數(shù)組中的True值計(jì)數(shù):
In [190]: arr = np.random.randn(100)
In [191]: (arr > 0).sum() # Number of positive values
Out[191]: 42
另外還有兩個(gè)方法any和all,它們對(duì)布爾型數(shù)組非常有用。any用于測(cè)試數(shù)組中是否存在一個(gè)或多個(gè)True,而all則檢查數(shù)組中所有值是否都是True:
In [192]: bools = np.array([False, False, True, False])
In [193]: bools.any()
Out[193]: True
In [194]: bools.all()
Out[194]: False
這兩個(gè)方法也能用于非布爾型數(shù)組,所有非0元素將會(huì)被當(dāng)做True。
排序
跟Python內(nèi)置的列表類型一樣,NumPy數(shù)組也可以通過(guò)sort方法就地排序:
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)行排序,只需將軸編號(hào)傳給sort即可:
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ù)組本身。計(jì)算數(shù)組分位數(shù)最簡(jiǎn)單的辦法是對(duì)其進(jìn)行排序,然后選取特定位置的值:
In [203]: large_arr = np.random.randn(1000)
In [204]: large_arr.sort()
In [205]: large_arr[int(0.05 * len(large_arr))] # 5% quantile
Out[205]: -1.5311513550102103
更多關(guān)于NumPy排序方法以及諸如間接排序之類的高級(jí)技術(shù),請(qǐng)參閱附錄A。在pandas中還可以找到一些其他跟排序有關(guān)的數(shù)據(jù)操作(比如根據(jù)一列或多列對(duì)表格型數(shù)據(jù)進(jìn)行排序)。
唯一化以及其它的集合邏輯
NumPy提供了一些針對(duì)一維ndarray的基本集合運(yùn)算。最常用的可能要數(shù)np.unique了,它用于找出數(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='
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])
拿跟np.unique等價(jià)的純Python代碼來(lái)對(duì)比一下:
In [210]: sorted(set(names))
Out[210]: ['Bob', 'Joe', 'Will']
另一個(gè)函數(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)
NumPy中的集合函數(shù)請(qǐng)參見表4-6。
4.4 用于數(shù)組的文件輸入輸出
NumPy能夠讀寫磁盤上的文本數(shù)據(jù)或二進(jìn)制數(shù)據(jù)。這一小節(jié)只討論NumPy的內(nèi)置二進(jìn)制格式,因?yàn)楦嗟挠脩魰?huì)使用pandas或其它工具加載文本或表格數(shù)據(jù)(見第6章)。
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)
如果文件路徑末尾沒(méi)有擴(kuò)展名.npy,則該擴(kuò)展名會(huì)被自動(dòng)加上。然后就可以通過(guò)np.load讀取磁盤上的數(shù)組:
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è)未壓縮文件中,將數(shù)組以關(guān)鍵字參數(shù)的形式傳入即可:
In [216]: np.savez('array_archive.npz', a=arr, b=arr)
加載.npz文件時(shí),你會(huì)得到一個(gè)類似字典的對(duì)象,該對(duì)象會(huì)對(duì)各個(gè)數(shù)組進(jìn)行延遲加載:
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)
4.5 線性代數(shù)
線性代數(shù)(如矩陣乘法、矩陣分解、行列式以及其他方陣數(shù)學(xué)等)是任何數(shù)組庫(kù)的重要組成部分。不像某些語(yǔ)言(如MATLAB),通過(guò)*對(duì)兩個(gè)二維數(shù)組相乘得到的是一個(gè)元素級(jí)的積,而不是一個(gè)矩陣點(diǎn)積。因此,NumPy提供了一個(gè)用于矩陣乘法的dot函數(shù)(既是一個(gè)數(shù)組方法也是numpy命名空間中的一個(gè)函數(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.]])
x.dot(y)等價(jià)于np.dot(x, y):
In [228]: np.dot(x, y)
Out[228]:
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.])
@符(類似Python 3.5)也可以用作中綴運(yùn)算符,進(jìn)行矩陣乘法:
In [230]: x @ np.ones(3)
Out[230]: array([ 6., 15.])
numpy.linalg中有一組標(biāo)準(zhǔn)的矩陣分解運(yùn)算以及諸如求逆和行列式之類的東西。它們跟MATLAB和R等語(yǔ)言所使用的是相同的行業(yè)標(biāo)準(zhǔn)線性代數(shù)庫(kù),如BLAS、LAPACK、Intel MKL(Math Kernel Library,可能有,取決于你的NumPy版本)等:
In [231]: from numpy.linalg import inv, qr
In [232]: X = np.random.randn(5, 5)
In [233]: mat = X.T.dot(X)
In [234]: inv(mat)
Out[234]:
array([[ 933.1189, 871.8258, -1417.6902, -1460.4005, 1782.1391],
[ 871.8258, 815.3929, -1325.9965, -1365.9242, 1666.9347],
[-1417.6902, -1325.9965, 2158.4424, 2222.0191, -2711.6822],
[-1460.4005, -1365.9242, 2222.0191, 2289.0575, -2793.422 ],
[ 1782.1391, 1666.9347, -2711.6822, -2793.422 , 3409.5128]])
In [235]: mat.dot(inv(mat))
Out[235]:
array([[ 1., 0., -0., -0., -0.],
[-0., 1., 0., 0., 0.],
[ 0., 0., 1., 0., 0.],
[-0., 0., 0., 1., -0.],
[-0., 0., 0., 0., 1.]])
In [236]: q, r = qr(mat)
In [237]: r
Out[237]:
array([[-1.6914, 4.38 , 0.1757, 0.4075, -0.7838],
[ 0. , -2.6436, 0.1939, -3.072 , -1.0702],
[ 0. , 0. , -0.8138, 1.5414, 0.6155],
[ 0. , 0. , 0. , -2.6445, -2.1669],
[ 0. , 0. , 0. , 0. , 0.0002]])
表達(dá)式X.T.dot(X)計(jì)算X和它的轉(zhuǎn)置X.T的點(diǎn)積。
表4-7中列出了一些最常用的線性代數(shù)函數(shù)。
4.6 偽隨機(jī)數(shù)生成
numpy.random模塊對(duì)Python內(nèi)置的random進(jìn)行了補(bǔ)充,增加了一些用于高效生成多種概率分布的樣本值的函數(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)
我們說(shuō)這些都是偽隨機(jī)數(shù),是因?yàn)樗鼈兌际峭ㄟ^(guò)算法基于隨機(jī)數(shù)生成器種子,在確定性的條件下生成的。你可以用NumPy的np.random.seed更改隨機(jī)數(shù)生成種子:
In [244]: np.random.seed(1234)
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])
表4-8列出了numpy.random中的部分函數(shù)。在下一節(jié)中,我將給出一些利用這些函數(shù)一次性生成大量樣本值的范例。
4.7 示例:隨機(jī)漫步
我們通過(guò)模擬隨機(jī)漫步來(lái)說(shuō)明如何運(yùn)用數(shù)組運(yùn)算。先來(lái)看一個(gè)簡(jiǎn)單的隨機(jī)漫步的例子:從0開始,步長(zhǎng)1和-1出現(xiàn)的概率相等。
下面是一個(gè)通過(guò)內(nèi)置的random模塊以純Python的方式實(shí)現(xiàn)1000步的隨機(jī)漫步:
In [247]: import random
.....: position = 0
.....: walk = [position]
.....: steps = 1000
.....: for i in range(steps):
.....: step = 1 if random.randint(0, 1) else -1
.....: position += step
.....: walk.append(position)
.....:
圖4-4是根據(jù)前100個(gè)隨機(jī)漫步值生成的折線圖:
In [249]: plt.plot(walk[:100])
圖4-4 簡(jiǎn)單的隨機(jī)漫步
不難看出,這其實(shí)就是隨機(jī)漫步中各步的累計(jì)和,可以用一個(gè)數(shù)組運(yùn)算來(lái)實(shí)現(xiàn)。因此,我用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()
有了這些數(shù)據(jù)之后,我們就可以沿著漫步路徑做一些統(tǒng)計(jì)工作了,比如求取最大值和最小值:
In [255]: walk.min()
Out[255]: -3
In [256]: walk.max()
Out[256]: 31
現(xiàn)在來(lái)看一個(gè)復(fù)雜點(diǎn)的統(tǒng)計(jì)任務(wù)——首次穿越時(shí)間,即隨機(jī)漫步過(guò)程中第一次到達(dá)某個(gè)特定值的時(shí)間。假設(shè)我們想要知道本次隨機(jī)漫步需要多久才能距離初始0點(diǎn)至少10步遠(yuǎn)(任一方向均可)。np.abs(walk)>=10可以得到一個(gè)布爾型數(shù)組,它表示的是距離是否達(dá)到或超過(guò)10,而我們想要知道的是第一個(gè)10或-10的索引。可以用argmax來(lái)解決這個(gè)問(wèn)題,它返回的是該布爾型數(shù)組第一個(gè)最大值的索引(True就是最大值):
In [257]: (np.abs(walk) >= 10).argmax()
Out[257]: 37
注意,這里使用argmax并不是很高效,因?yàn)樗鼰o(wú)論如何都會(huì)對(duì)數(shù)組進(jìn)行完全掃描。在本例中,只要發(fā)現(xiàn)了一個(gè)True,那我們就知道它是個(gè)最大值了。
一次模擬多個(gè)隨機(jī)漫步
如果你希望模擬多個(gè)隨機(jī)漫步過(guò)程(比如5000個(gè)),只需對(duì)上面的代碼做一點(diǎn)點(diǎn)修改即可生成所有的隨機(jī)漫步過(guò)程。只要給numpy.random的函數(shù)傳入一個(gè)二元元組就可以產(chǎn)生一個(gè)二維數(shù)組,然后我們就可以一次性計(jì)算5000個(gè)隨機(jī)漫步過(guò)程(一行一個(gè))的累計(jì)和了:
In [258]: nwalks = 5000
In [259]: nsteps = 1000
In [260]: draws = np.random.randint(0, 2, size=(nwalks, nsteps)) # 0 or 1
In [261]: steps = np.where(draws > 0, 1, -1)
In [262]: walks = steps.cumsum(1)
In [263]: walks
Out[263]:
array([[ 1, 0, 1, ..., 8, 7, 8],
[ 1, 0, -1, ..., 34, 33, 32],
[ 1, 0, -1, ..., 4, 5, 4],
...,
[ 1, 2, 1, ..., 24, 25, 26],
[ 1, 2, 3, ..., 14, 13, 14],
[ -1, -2, -3, ..., -24, -23, -22]])
現(xiàn)在,我們來(lái)計(jì)算所有隨機(jī)漫步過(guò)程的最大值和最小值:
In [264]: walks.max()
Out[264]: 138
In [265]: walks.min()
Out[265]: -133
得到這些數(shù)據(jù)之后,我們來(lái)計(jì)算30或-30的最小穿越時(shí)間。這里稍微復(fù)雜些,因?yàn)椴皇?000個(gè)過(guò)程都到達(dá)了30。我們可以用any方法來(lái)對(duì)此進(jìn)行檢查:
In [266]: hits30 = (np.abs(walks) >= 30).any(1)
In [267]: hits30
Out[267]: array([False, True, False, ..., False, True, False], dtype=bool)
In [268]: hits30.sum() # Number that hit 30 or -30
Out[268]: 3410
然后我們利用這個(gè)布爾型數(shù)組選出那些穿越了30(絕對(duì)值)的隨機(jī)漫步(行),并調(diào)用argmax在軸1上獲取穿越時(shí)間:
In [269]: crossing_times = (np.abs(walks[hits30]) >= 30).argmax(1)
In [270]: crossing_times.mean()
Out[270]: 498.88973607038122
請(qǐng)嘗試用其他分布方式得到漫步數(shù)據(jù)。只需使用不同的隨機(jī)數(shù)生成函數(shù)即可,如normal用于生成指定均值和標(biāo)準(zhǔn)差的正態(tài)分布數(shù)據(jù):
In [271]: steps = np.random.normal(loc=0, scale=0.25,
.....: size=(nwalks, nsteps))
4.8 結(jié)論
雖然本書剩下的章節(jié)大部分是用pandas規(guī)整數(shù)據(jù),我們還是會(huì)用到相似的基于數(shù)組的計(jì)算。在附錄A中,我們會(huì)深入挖掘NumPy的特點(diǎn),進(jìn)一步學(xué)習(xí)數(shù)組的技巧。
總結(jié)
以上是生活随笔為你收集整理的python输入一个数组输出24进制式的时间_【翻译】《利用Python进行数据分析·第2版》第4章(下)NumPy基础:数组和矢量计算...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用 ChatGPT 做表格真香,只需动嘴
- 下一篇: 使用python 下载_使用python