標籤:concat 讀寫 txt 推斷 版本 間隔 二進位 false 面向
http://www.cnblogs.com/batteryhp/p/5000104.html
第四章 Numpy基礎:數組和向量計算
第一部分:numpy的ndarray:一種多維陣列對象
實話說,用numpy的主要目的在於應用向量化運算。Numpy並沒有多麼進階的資料分析功能,理解Numpy和面向數組的計算能有助於理解後面的pandas.按照課本的說法,作者關心的功能主要集中於:
- 用於資料整理和清理、子集構造和過濾、轉換等快速的向量化運算
- 常用的數組解法,如排序、唯一化、集合運算等
- 高效的描述統計和資料彙總/摘要運算
- 用於異構資料集的合并/串連運算的資料對齊和關係型資料運算
- 將條件邏輯表述為數組運算式(而不是帶有if-elif-else分支的迴圈)
- 資料的分組運算(彙總、轉換、函數應用等)。
作者說了,可能還是pandas更好一些,我感覺顯然pandas更進階,其中的函數真是太方便了,資料框才是最好的資料結構。只是,Numpy中的函數之類的是基礎,需要熟悉。
NumPy的ndarray:一種多維陣列對象
ndarray對象是NumPy最重要的對象,特點是向量化。ndarray每個元素的資料類型必須相同,每個數組有兩個屬性:shape和dtype.
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltdata = [[1,2,5.6],[21,4,2]]data = np.array(data)print data.shapeprint data.dtypeprint data.ndim
>>>
(2, 3)
float64
2
array函數接受一切序列型的對象(包括其他數組),然後產生新的含有傳入資料的NumPy數組,array會自動推斷出一個合適的資料類型。還有一個方法是ndim:這個翻譯過來叫維度,標明資料的維度。上面的例子是兩維的。zeros和ones可以建立指定長度或形狀全為0或1的數組。empty可以建立一個沒有任何具體值的數組,arange函數是python內建函數range的數組版本。
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltdata = [[1,2,5.6],[21,4,2],[2,5,3]]data1 = [[2,3,4],[5,6,7,3]]data = np.array(data)data1 = np.array(data1)arr1 = np.zeros(10)arr2 = np.ones((2,3))arr3 = np.empty((2,3,4))print arr1print arr2print arr3print arr3.ndim
>>>
[ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[[ 1. 1. 1.]
[ 1. 1. 1.]]
[[[ 3.83889007e-321 0.00000000e+000 0.00000000e+000 0.00000000e+000]
[ 0.00000000e+000 0.00000000e+000 0.00000000e+000 0.00000000e+000]
[ 0.00000000e+000 0.00000000e+000 0.00000000e+000 0.00000000e+000]]
[[ 0.00000000e+000 0.00000000e+000 0.00000000e+000 0.00000000e+000]
[ 0.00000000e+000 0.00000000e+000 0.00000000e+000 0.00000000e+000]
[ 0.00000000e+000 0.00000000e+000 0.00000000e+000 0.00000000e+000]]]
3
上面是常用的產生數組的函數。
ndarray的資料類型
dtype(資料類型)是一個特殊的對象。它含有ndarray將一塊記憶體解釋為指定資料類型所需的資訊。他是NumPy如此靈活和強大的原因之一。多數情況下,它們直接映射到相應的機器表示,這使得“讀寫磁碟上的位元據流”以及“整合低級語言代碼(C\Fortran)”等工作變得更加簡單。dtype命名方式為,類型名+表示元素位長的數字。標準雙精確度浮點型資料需要佔用8位元組(64位)。記作float64.常見的資料類型為:
我終於找到了f4,f8的含義了……布爾型資料的代碼倒是很有個性。函數astype可以強制轉換資料類型。
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltarr = np.array([1,2,3,4,5])print arr.dtypefloat_arr = arr.astype(np.float64)print float_arr.dtypearr1 = np.array([2.3,4.2,32.3,4.5])#浮點型會被整型截斷print arr1.astype(np.int32)#一個全是數位字串也可以轉換為數實值型別arr2 = np.array([‘2323.2‘,‘23‘])print arr2.astype(float)#數組的dtype還有一個用法int_array = np.arange(10)calibers = np.array([.22,.270,.357,.44,.50],dtype = np.float64)print int_array.astype(calibers.dtype)print np.empty(10,‘u4‘)
調用astype總會建立一個新的數組(原始數組的一個拷貝),即使和原來的資料類型相同。警告:浮點數只能表示近似數,比較小數的時候要注意。
數組與標量之間的運算
向量化(vectorization)是數組最重要的特點了。可以避免(顯示)迴圈。注意加減乘除的向量化運算。不同大小的數組之間的運算叫廣播(broadcasting)。
索引和切片,不再贅述,注意的是 廣播的存在使得數組即使只賦一個值也會被廣播到所有數組元素上,其實和R語言中自動補齊功能相同。下面的性質有點蛋疼:跟列表最重要的區別在於,數組切片是原始數組的視圖,對視圖的任何修改都會反映到來源資料上。即使是下面的情況:
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltarr = np.array([1,2,3,4,5,6,7,8,9])arr1 = arr[1:2]arr1[0] = 10print arr#如果想得到拷貝,需要顯示地複製一份arr2 = arr[3:4].copy()arr2[0] = 10print arrarr2d = np.array([[1,2,3],[4,5,6],[7,8,9]])#下面兩種索引方式等價print arr2d[0][2]print arr2d[0,2]print arr2d[:,1] #注意這裡的方式和下面的方式print arr2d[:,:1]arr3d = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[[10,11,12]]]])print arr3d[(1,0)]
>>>
[ 1 10 3 4 5 6 7 8 9]
[ 1 10 3 4 5 6 7 8 9]
3
3
[2 5 8] #注意這裡的方式和下面的方式
[[1]
[4]
[7]]
[7, 8, 9]
布爾型索引
這裡的布爾型索引就是TRUE or FALSE索引。==、!=、-(表示否定)、&(並且)、|(或者)。注意布爾型索引選取數組中的資料,將建立資料的副本。python關鍵字and、or無效。
花式索引(Fancy indexing)
花式索引指的是利用整數數組進行索引。
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltarr = np.arange(32).reshape(8,4)print arr#注意這裡的向量式方式print arr[[1,5,7,2],[0,3,1,2]]print arr[[1,5,7,2]][:,[0,3,1,2]]#也可以使用np.ix_函數,將兩個一維整數數組組成選取方形地區的索引器print arr[np.ix_([1,5,7,2],[0,3,1,2])]>>>[[ 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]][ 4 23 29 10][[ 4 7 5 6] [20 23 21 22] [28 31 29 30] [ 8 11 9 10]][[ 4 7 5 6] [20 23 21 22] [28 31 29 30] [ 8 11 9 10]]
花式索引總是將資料複製到新數組中,跟切片不同,一定要注意下面的區別:
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltarr = np.arange(32).reshape(8,4)arr1 = np.arange(32).reshape(8,4)#注意下面得到的結果是一樣的arr3 = arr[[1,2,3]][:,[0,1,2,3]]arr3_1 = arr1[1:4][:]#注意下面是區別了arr3[0,1] = 100 #花式索引得到的是複製品,重新賦值以後arr不變化arr3_1[0,1] = 100 #切片方式得到的是一個視圖,重新賦值後arr1會變化print arr3print arr3_1print arrprint arr1>>>[[ 4 100 6 7] [ 8 9 10 11] [ 12 13 14 15]][[ 4 100 6 7] [ 8 9 10 11] [ 12 13 14 15]][[ 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]][[ 0 1 2 3] [ 4 100 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]]
數組轉置和軸轉換
轉置transpose,是一種對來源資料的視圖,不會進行複製。調用T就可以。np中的矩陣乘積函數為np.dot。
比較複雜的是高維數組:
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltarr = np.arange(24).reshape((2,3,4))#下面解釋一下transpose:#(1,0,2) 是將reshape中的參數 (2,3,4) 進行變化 ,變為(3,2,4)#但是由於是轉置,所以是將所有元素的下標都進行了上述變化,比如 12這個元素,原來索引為 (1,0,0) ,現在為 (0,1,0)arr1 = arr.transpose((1,0,2))arr2 = arr.T #直接用T是變為了(4,3,2)的形式#arr3 = np.arange(120).reshape((2,3,4,5))#arr4 = arr3.T #直接用T就是將形式變為 (5,4,3,2)#ndarray還有swapaxes方法,接受一對軸編號arr5 = arr.swapaxes(1,2)#print arr#print arr1#print arr2#print arr3#print arr4print arr5>>>[[[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]] [[12 16 20] [13 17 21] [14 18 22] [15 19 23]]]
第二部分是關於一些元素級函數:即作用於數組每個元素上的函數,用過R語言之後就覺得其實沒什麼了。
下面是一些常見的向量化函數(姑且這麼叫吧)。
下面是幾個例子:
#-*- encoding:utf-8 -*-import numpy as npimport numpy.random as nprimport pandas as pd#接收兩個數組的函數,對應值取最大值x = npr.randn(8)y = npr.randn(8)#注意不是max函數z = np.maximum(x,y)print x,y,z#雖然並不常見,但是一些ufunc函數的確可以返回多個數組。modf函數就是一例,用來分隔小數的整數部分和小數部分,是python中divmod的向量化版本arr = npr.randn(8)print np.modf(arr)#ceil函數取天花板,不小於這個數的最小整數print np.ceil(arr)#concatenate函數是將兩個numpy數組串連,注意要組成元組方式再串連#arr = np.concatenate((arr,np.array([0,0])))#logical_not函數, 非 函數#print np.logical_not(arr)print np.greater(x,y)print np.multiply(x,y)
第三部分:利用數組進行資料處理
作者說向量化數組運算比純pyhton方式快1-2個數量級(or more),又一次強調了broadcasting作用很強大。
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as plt#假設想在一個二維網格上計算一個 sqrt(x^2 + y^2)#產生-5到5的網格,間隔0.01points = np.arange(-5,5,0.01)#meshgrid返回兩個二維矩陣,描述出所有(-5,5)* (-5,5)的點對xs,ys = np.meshgrid(points,points)z = np.sqrt(xs ** 2 + ys ** 2)#print xs#print ys#不做個圖都對不起觀眾#imshow函數,展示z是一個矩陣,cmap就是colormap,用的時候值得研究plt.imshow(z,cmap=plt.cm.gray)plt.colorbar()plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")plt.show()
上面的畫圖語句在用的時候還需要好好研究一下。
下面的一個例子是np.where函數,簡潔版本的if-else。
‘‘‘#np.where函數通常用於利用已有的數組生產新的數組arr = npr.randn(4,4)#正值賦成2,負值為-2print np.where(arr > 0,2,-2)#注意這裡的用法print np.where(arr > 0,2,arr)#可以用where表示更為複雜的邏輯表達#兩個布爾型數組cond1和cond2,4種不同的組合賦值不同#注意:按照課本上的說法,下面的語句是從左向右運算的,不是從做內層括弧計算起的;這貌似與python的文法不符np.where(cond1 & cond2,0,np.where(cond1,1,np.where(cond2,2,3)))#不過感覺沒有更好的寫法了。#書上“投機取巧”的式子,前提是True = 1,False = 0result = 1 * (cond1 - cond2) + 2 * (cond2 & -cond1) + 3 * -(cond1 | cond2)‘‘‘
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport numpy.random as npr#值得注意的是,mean、sum這樣的函數,會有一個參數axis表示對哪個維度求值arr = np.array([[0,1,2],[3,4,5],[6,7,8]])#cumsum不是彙總函式,維度不會減少print arr.cumsum(0)
下面是常用的數學函數:
用於布爾型數組的方法
sum經常用於True的加和;any和all分別判斷是否存在和是否全部為True。
排序及唯一化
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport numpy.random as npr#sort函數是就地排序arr = npr.randn(10)print arrarr.sort()print arr#多維陣列可以按照維度排序,把軸編號傳遞給sort即可arr = npr.randn(5,3)print arr#sort傳入1,就是把第1軸排好序,即按列arr.sort(1)print arr#np.sort返回的是排序副本,不是就地排序#輸出5%分位元arr_npr = npr.randn(1000)arr_npr.sort()print arr_npr[int(0.05 * len(arr_npr))]#pandas中有更多排序、分位元之類的函數,直接可以取分位元的,第二章的例子中就有#numpy中有unique函數,唯一化函數,R語言中也有names = np.array([‘Bob‘,‘Joe‘,‘Will‘,‘Bob‘,‘Will‘])print sorted(set(names))print np.unique(names)values = np.array([6,0,0,3,2,5,6])#in1d函數用來查看一個數組中的元素是否在另一個數組中,名字挺好玩,注意返回的長度與第一個數組相同print np.in1d(values,[6,2,3])
下面是常用集合運算
用於數組的檔案輸入輸出
NumPy能夠讀寫磁碟上的文本資料或位元據。後面的章節將會給出一些pandas中用於將表格型資料讀取到記憶體的工具。
np.save 和 np.load是讀寫磁碟資料的兩個主要函數。預設情況下,數組是以未壓縮的原始二進位檔案格式儲存在副檔名為.npy的檔案中。
#-*- encoding:utf-8 -*-import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport numpy.random as npr‘‘‘arr = np.arange(10)np.save(‘some_array‘,arr)np.savez(‘array_archive.npz‘,a = arr,b = arr)arr1 = np.load(‘some_array.npy‘)arch = np.load(‘array_archive.npz‘)print arr1print arch[‘a‘]‘‘‘#下面是存取文字檔,pandas中的read_csv和read_table是最好的了#有時需要用np.loadtxt或者np.genfromtxt將資料載入到普通的NumPy數組中#這些函數有許多選項使用:指定各種分隔字元,針對特定列的轉換器函數,需要跳過的行數等#np.savetxt執行的是相反的操作:將數組寫到以某種分隔字元隔開的文字檔中#genfromtxt跟loadtxt差不多,只不過它面向的是結構化數組和缺失資料處理
線性代數
關於線性代數的一些函數,NumPy的linalg中有很多關於矩陣的函數,與MATLAB、R使用的是相同的行業標準級Fortran庫。
隨機數產生
NumPy.random模組對Python內建的random進行了補充,增加了一些用於高效產生多種機率分布的樣本值的函數。
#-*- encoding:utf-8 -*-import numpy as npimport numpy.random as nprfrom random import normalvariate#產生標準正態4*4樣本數組samples = npr.normal(size = (4,4))print samples#從下面的例子中看出,如果產生大量樣本值,numpy.random快了不止一個數量級N = 1000000#xrange()雖然也是內建函數,但是它被定義成了Python裡一種類型(type),這種類型就叫做xrange.#下面的迴圈中,for _ in xrange(N) 非常good啊,查了一下和range的關係,兩者都用於迴圈,但是在大型迴圈時,xrange好得多%timeit samples = [normalvariate(0,1) for _ in xrange(N)]%timeit npr.normal(size = N)
範例:隨機漫步
#-*- encoding:utf-8 -*-import numpy as npimport random #這裡的random是python內建的模組import matplotlib.pyplot as pltposition = 0walk = [position]steps = 1000for i in xrange(steps): step = 1 if random.randint(0,1) else -1 position += step walk.append(position)plt.plot(walk)plt.show()#下面看看簡單的寫法nsteps = 1000draws = np.random.randint(0,2,size = nsteps)steps = np.where(draws > 0,1,-1)walk = steps.cumsum()plt.plot(walk)plt.show()#argmax函數返回數組第一個最大值的索引,但是在這argmax不高效,因為它會掃描整個數組print (np.abs(walk) >= 10).argmax()nwalks = 5000nsteps = 1000draws = np.random.randint(0,2,size = (nwalks,nsteps))steps = np.where(draws > 0,1,-1)walks = steps.cumsum(1)print walks.max()print walks.min()#這裡的any後面的參數1表示每行(軸為1)是否存在truehist30 = (np.abs(walks) >= 30).any(1)print hist30print hist30.sum() #這就是有多少行超過了30#這裡argmax的參數1就是crossing_time = (np.abs(walks[hist30]) >= 30).argmax(1)print crossing_time.mean()X = range(1000)plt.plot(X,walks.T)plt.show()
NumPy寫完了,接下來寫pandas.NumPy寫的還好,比較順利。
《利用python進行資料分析》讀書筆記--第四章 numpy基礎:數組和向量計算