本人小白一枚,最近在精讀《利用Python進行數據分析》雖然書中的代碼實現是python2版本的,但准備手工把其中的代碼用Python3敲一遍,希望可以盡快讀完。
Numpy簡介
Numpy(Numerical Python的簡稱)是高性能科學計算和數據分析的基礎包。其部分功能如下:
①ndarray,一個具有矢量算術運算和復雜廣播能力的快速且節省空間的多維數組。
②用於對整組數據進行快速運算的標准數學函數(無需編寫循環)。
③用於讀寫磁盤數據的工具以及用於操作內存映射文件的工具。
④線性代數、隨機數生成以及傅里葉變換功能。
⑤用於集成由C、C++、Fortran等語言編寫的代碼的工具。
一、NumPy的ndarray:一種多維數組對象
每個數組都有一個shape(一個表示各維度大小的元組)和一個dtype(一個用於說明數組數據類型的對象)
1、創建ndarray
import numpy as np data1 = [6,7.5,8,0,1] #創建列表 arr1 = np.array(data1) #轉換為數組 print(arr1) print(arr1.dtype) #數據類型保存在dtype對象中 data2 = [[1,2,3,4],[5,6,7,8]] #創建嵌套序列(由等長列表組成的列表) arr2 = np.array(data2) #轉換為多維數組 print(arr2) print(arr1.dtype) print(arr1.shape)
除np.array之外,還有一些函數也可以新建數組。比如,zeros和ones分別可以創建指定長度或形狀的全0或全1數組。empty可以創建一個沒有任何具體值的數組。要用這些方法創建多維數組,只需傳入一個表示形狀的元組即可:
print(np.zeros(10)) #創建指定長度(10)的全0數組 print(np.ones(2,4)) #創建指定長度的(2行4列二維)的全1數組 print(np.empty((2, 3, 2)))
第一個參數表示數組的維度
注意:認為np.empty會返回全0數組的想法是不安全的。很多情況下(如前所示),它返回的都是一些未初始化的垃圾值。arange是Python內置函數range的數組版:
range(10) #創建指定數量的順序列表(內置函數,默認0開始) print(np.arange(15)) #創建指定數量的順序數組 arr1=np.array([1,2,3],dtype=np.float64) #創建特定數據類型的數組
數組創建函數:
2、ndarray的數據類型
dtype(數據類型)是一個特殊的對象,它含有ndarray將一塊內存解釋為特定數據類型所需的信息。
dtype是NumPy如此強大和靈活的原因之一。多數情況下,它們直接映射到相應的機器表示,這使得“讀寫磁盤上的二進制數據流”以及“集成低級語言代碼(如C、Fortran)”等工作變得更加簡單。數值型dtype的命名方式相同:一個類型名(如float或int),后面跟一個用於表示各元素位長的數字。標准的雙精度浮點值(即Python中的float對象)需要占用8字節(即64位)。因此,該類型在NumPy中就記作float64。下圖列示了NumPy所支持的全部數據類型。
注意:記不住這些NumPy的dtype也沒關系,新手更是如此。通常只需要知道你所處理的數據的大致類型是浮點數、復數、整數、布爾值、字符串,還是普通的Python對象即可。當你需要控制數據在內存和磁盤中的存儲方式時(尤其是對大數據集),那就得了解如何控制存儲類型。
轉換數據類型
可以通過ndarray的astype方法顯式地轉換其dtype。
arr = np.array([1,2,3,4,5]) print(arr.dtype) float_arr = arr.astype(np.float32) print(float_arr.dtype)
注意:浮點數(比如float64和float32)只能表示近似的分數值。在復雜計算中,由於可能會積累一些浮點錯誤,因此比較操作只能在一定小數位以內有效。
3、數組和標量之間的運算
數組很重要,因為它使你不用編寫循環即可對數據執行批量運算。這通常就叫做矢量化(vectorization)。大小相等的數組之間的任何算術運算都會將運算應用到元素級。
arr=np.array([[1.,2.,3.],[4.,5.,6.]]) #創建二維數組 arr*arr #行列號相同的數組元素間運算 arr-arr 1/arr arr*0.5
4、基本的索引和切片
從表面上看,它們跟Python列表的功能差不多,跟列表最重要的區別在於,數組切片是原始數組的視圖。這意味着數據不會被復制,視圖上的任何修改都會直接反映到源數組上:
arr=np.arange(10) arr[5] #索引第6個元素 arr[5:8] #索引第6到第9個元素作為數組 arr[5:8]=12 #令第6到第9個元素等於12 arr_slice=arr[5:8] #數組切片是原始數據的視圖,視圖上的任何修改都會反映到原數組 arr_slice[:]=64 #將數組切片的全部元素改為64 arr[5:8].copy() #得到數組切片的一份副本 arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]]) arr2d[2] #索引二維數組第3行 arr2d[0][2] arr2d[0,2] #等價索引1行3列元素 arr2d[:2] #索引第1行和第2行(不含第3行) arr2d[:,:1] #索引第1列 arr2d[:-2] #使用負數索引將從尾部開始選取行
二維數組的索引方式
5、切片索引
ndarray的切片語法跟Python列表這樣的一維對象差不多
可以一次性傳入多個切片,就像傳入多個索引那樣。
6、布爾型索引
names = np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe']) names =='Bob' #array([ True, False, False, True, False, False, False], dtype=bool) data = np.random.randn(7,4) data[names=='Bob'] data[names=='Bob',2:] #布爾型數組的長度必須跟被索引的軸長度一致 names !='Bob' #不等於 data[-(names=='Bob')] #負號(-)對條件進行否定 #Python關鍵字and和or在布爾型數組中無效。
通過布爾型數組設置值是一種經常用到的手段。為了將data中的所有負值都設置為0,我們可以這樣:
data[data < 0] = 0
7、花式索引
指的是利用整數數組進行索引,以特定的順序選取子行。
arr = np.empty((8,4)) for i in range(8): arr[i] = i arr[[2,3,0]] #以特定順序選取行子集,傳入整數列表或ndarray
如果想要選出的是矩形區域,有兩種方法,一種是data[[1,3]][:,[1,3]],相當於先在軸0做一次索引,然后再在軸1做一次索引。另一種是用np.ix_函數將兩個一維數組轉化成選取矩形的索引器:data[np.ix_([1,3],[1,3])]。
用np.ix_函數,它可以將兩個一維整數數組轉換為一個用於選取方形區域的索引器。
8、數組轉置和軸對換
轉置(transpose)是重塑的一種特殊形式,它返回的是源數據的視圖(不會進行任何復制操作)。數組不僅有transpose方法,還有一個特殊的T屬性。
二、通用函數:快速的元素級數組函數
通用函數(即ufunc)是一種對ndarray中的數據執行元素級運算的函數。你可以將其看做簡單函數(接受一個或多個標量值,並產生一個或多個標量值)的矢量化包裝器。
import numpy as np arr=np.arange(10) np.sqrt(arr) #計算各元素的平方根(arr**0.5) exp #計算各元素指數ex; abs #絕對值; np.add(x,y) #x、y數組中對應元素相加; subtract #相減; multiply #相乘; divide #相除;
1、利用數組進行數據處理
用數組表達式代替循環的做法,通常被稱為矢量化。
import numpy as np points = np.arange(-5, 5, 0.01) xs, ys = np.meshgrid(points,points) z = np.sqrt(xs **2 + ys **2) print(z)
2、將條件邏輯表述為數組運算
numpy.where函數是三元表達式x if condition else y的矢量化版本。
如:
import numpy as np xarr = np.array([1.1,1.2,1.3,1.4,1.5]) yarr = np.array([2.1,2.2,2.3,2.4,2.5]) cond = np.array([True,False,True,True,False])
假設我們想要根據cond中的值選取xarr和yarr的值:當cond中的值為True時,選取xarr的值,否則從yarr中選取。列表推導式的寫法應該如下所示:
使用np.where
import numpy as np xarr=np.array([1.1,1.2,1.3,1.4,1.5]) #兩個數值數組 yarr=np.array([2.1,2.2,2.3,2.4,2.5]) cond=np.array([True,False,True,True,False]) #一個布爾數組 result=np.where(cond,xarr,yarr) #三元表達式
3、數學和統計方法
可以通過數組上的一組數學函數對整個數組或某個軸向的數據進行統計計算。sum、mean以及標准差std等聚合計算(aggregation,通常叫做約簡(reduction))既可以當做數組的實例方法調用,也可以當做頂級NumPy函數使用:
arr=np.random.randn(5,4) arr.mean(); np.mean(arr); arr.sum(); arr.mean(axis=1) #計算該軸上的統計值(0為列,1為行)
4、用於布爾型數組的方法
布爾值會被強制轉換為1(True)和0(False)。因此,sum經常被用來對布爾型數組中的True值計數:
arr=randn(100) (arr>0).sum() #正值的數量 bools.any() #用於測試數組中是否存在一個或多個True bools.all() #用於測試數組中所有值是否都是True
5、排序
跟Python內置的列表類型一樣,NumPy數組也可以通過sort方法就地排序:
arr=randn(8) arr.sort() arr=randn(5,3) arr.sort(0) #二維數組按列排序; arr.sort(1) #二維數組按行排序
6、唯一化
ints=np.array([3,3,3,2,2,1,1,4,4]) np.unique(names) #找出數組中的唯一值並返回已排序的結果
7、用於數組的文件輸入輸出
Numpy能夠讀寫磁盤上的文本數據或二進制數據。
arr=np.arange(10) np.save('some_array',arr) #數組以未壓縮的原始二進制格式保存在.npy文件中 np.load('some_array') #通過np.load讀取磁盤上的數組 np.savez('array_archive.npz',a=arr,b=arr) #將多個數組以保存在一個壓縮文件中 a=np.arange(0,12,0.5).reshape(4,-1) np.savetxt(r'E:\\knakan\\a.txt',a) #缺省按照’%.18e’格式保存數據,以空格分隔 np.loadtxt(r'E:\\kankan\\a.txt') np.savetxt(r'\kankan\\a.txt',a,fmt="%d"delimiter=",") #改為保存為整數,以逗號分隔 np.loadtxt(r'E:\\kankan\\a.txt',delimiter=",") #讀入時也需指定逗號分隔
8、 線性代數
x=np.array([[1.,2.,3.],[4.,5.,6.]]) y=np.array([[6.,23.],[-1,7],[8,9]]) x.dot(y) #矩陣乘法,相當於np.dot(x,y)