數據分析三劍客:Numpy,Pandas,Matplotlibpython
NumPy(Numerical Python) 是 Python 語言的一個擴展程序庫,支持大量的維度數組與矩陣運算,此外也針對數組運算提供大量的數學函數庫。數組
numpy是基於c語言開發,因此這使得numpy的運行速度很快,高效率運行就是numpy的一大優點。安全
首先·咱們要導入numpy包,通常咱們都把它命名爲np:數據結構
In [1]: import numpy as np
接着就能夠生成一個numpy一維數組: dom
In [2]: a = np.array([[1,2,3]],dtype=np.int32) In [3]: a Out[3]: array([1, 2, 3])
numpy中定義的最重要的數據結構是稱爲ndarray的n維數組類型,這個結構引用了兩個對象,一塊用於保存數據的存儲區域和一個用於描述元素類型的dtype對象: 函數
二維數組的生成在python中咱們還能夠用到list列表,若是用list來表示[1,2,3],因爲list中的元素能夠是任何對象,因此list中保存的是對象的指針,若是要保存[1,2,3]就須要三個指針和三個整數對象,是比較浪費內存資源和cpu計算時間的,而ndarray是一種保存單一數據類型的多維數組結構,在數據處理上比list列表要快上不少,在這裏咱們能夠用%timeit命令來檢測二者的數據處理速度:oop
In [9]: a = range(1000) In [10]: %timeit[i**2 for i in a] 381 µs ± 6.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) In [11]: b = np.arange(1000) In [12]: %timeit b**2 1.41 µs ± 18 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
因爲相同數據大小的array運算直接做用到元素級上這一numpy特性,結果顯而易見,在數據處理上numpy數組比使用for循環的list列表快的不是一點兩點。 spa
這裏生成一個3×3的矩陣做爲例子:指針
In [2]: data = np.array([[1,2,3],[4,5,6],[7,8,9]]) # 等價於data=np.arange(1,10).reshape(3,3) In [3]: data Out[3]: array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
查看矩陣信息:code
In [6]: data.shape # 返回元組,表示n行n列 Out[6]: (3, 3) In [7]: data.dtype # 返回數組數據類型 Out[7]: dtype('int32') In [8]: data.ndim # 返回是幾維數組 Out[8]: 2
轉換數據類型:
In [11]: a = data.astype(float) # 拷貝一份新的數組 In [12]: a.dtype Out[12]: dtype('float64')
數組之間的計算:
In [15]: data+data Out[15]: array([[ 2, 4, 6], [ 8, 10, 12], [14, 16, 18]]) In [16]: data*data Out[16]: array([[ 1, 4, 9], [16, 25, 36], [49, 64, 81]])
能夠看出相同規格的數組計算是直接做用在其元素級上的,那不一樣的規格的數組是否能進行運算呢,咱們來看下這個例子:
In [18]: data1 = np.array([[1,2],[1,2]]) #生成一個2x2numpy數組 In [19]: data+data1 --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-19-f2592a975589> in <module>() ----> 1 data+data1 ValueError: operands could not be broadcast together with shapes (3,3) (2,2)
咱們能夠看出不一樣規格的數組一塊兒計算的話是會報出廣播錯誤的,那是否是能夠下結論了,別急咱們再來看下方兩個特殊例子:
In [20]: data2 = np.array([[1,2,3]]) In [21]: data + data2 Out[21]: array([[ 2, 4, 6], [ 5, 7, 9], [ 8, 10, 12]]) In [22]: data3 = np.array([[1],[2],[3]]) In [23]: data+data3 Out[23]: array([[ 2, 3, 4], [ 6, 7, 8], [10, 11, 12]])
data2數組的列數量與data數組相等,data3數組的行數量與data數組相等,這兩個numpy數組雖然規格與data數組不同,但卻依然能夠與data數組進行運算。
數組的切片:
In [24]: data[:2] # 沿着行(axis=0)進行索引 Out[24]: array([[1, 2, 3], [4, 5, 6]]) In [25]: data[:2,:2] # 先沿着行(axis=0)進行索引,再沿着列(axis=1)進行索引 Out[25]: array([[1, 2], [4, 5]]) In [26]: data[1,0:2] # 下標是從0開始 Out[26]: array([4, 5])
這裏須要注意的是,切片操做是在原始數組上建立一個視圖view,這只是訪問數組數據的一種方式。 所以原始數組不會被複制到內存中,傳遞的是一個相似引用的東西,與上面的astype()方法是兩種不一樣的拷貝方式,這裏咱們來看一個例子:
In [32]: a = data[1] In [33]: a Out[33]: array([4, 5, 6]) In [34]: a[:] = 0 In [35]: data Out[35]: array([[1, 2, 3], [0, 0, 0], [7, 8, 9]])
當切片對象a改變時,data的對應值也會跟着改變,這是在咱們平常數據處理中有時會疏忽的一個點,最安全的複製方法是使用
copy() 方法進行淺拷貝:
In [36]: a = data[1].copy() In [37]: a Out[37]: array([0, 0, 0]) In [38]: a[:]=9 In [39]: data Out[39]: array([[1, 2, 3], [0, 0, 0], [7, 8, 9]])
數組的布爾索引:
In [43]: data Out[43]: array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) In [44]: data>3 Out[44]: array([[False, False, False], [ True, True, True], [ True, True, True]]) In [45]: data[data>3] # 找出大於3的元素 Out[45]: array([4, 5, 6, 7, 8, 9])
數組的邏輯表達處理:
In [46]: np.where(data>3,1,0) # 大於3的標記爲1,小於等於3的標記爲0 Out[46]: array([[0, 0, 0], [1, 1, 1], [1, 1, 1]])
數組的經常使用統計操做:
In [47]: data.mean(axis=0) # 沿着行(axis=0)進行索引,求出其平均值 Out[47]: array([4., 5., 6.]) In [49]: data.std() # 求出所有元素的方差 Out[49]: 2.581988897471611 In [50]: (data>3).sum() # 統計數組中元素大於3的個數 Out[50]: 6 In [51]: data.any() # 數組中是否存在一個或多個true Out[51]: True In [52]: data.all() # 數組中是否所有數都是true Out[52]: True In [53]: data.cumsum(0) # 沿着行(axis=0)進行索引,進行累加 Out[53]: array([[ 1, 2, 3], [ 5, 7, 9], [12, 15, 18]], dtype=int32) In [54]: data.cumprod(1) # 沿着列(axis=1)進行索引,進行累乘 Out[54]: array([[ 1, 2, 6], [ 4, 20, 120], [ 7, 56, 504]], dtype=int32)
數組的排序操做:
In [55]: data=np.random.randn(4,4) In [56]: data Out[56]: array([[ 1.58669867, 1.57692769, -1.85828013, 1.17201164], [ 1.68160714, -0.83957549, -0.33771694, -0.33782379], [-0.03148106, -0.97819034, 0.51126626, -0.08184963], [-0.02822319, -0.31934723, 0.70764701, 0.80444954]]) In [57]: data.sort(0) # 沿着行(axis=0)進行索引,並進行升序排序 In [58]: data Out[58]: array([[-0.03148106, -0.97819034, -1.85828013, -0.33782379], [-0.02822319, -0.83957549, -0.33771694, -0.08184963], [ 1.58669867, -0.31934723, 0.51126626, 0.80444954], [ 1.68160714, 1.57692769, 0.70764701, 1.17201164]]) In [59]: data[::-1] # 降序操做 Out[59]: array([[ 1.68160714, 1.57692769, 0.70764701, 1.17201164], [ 1.58669867, -0.31934723, 0.51126626, 0.80444954], [-0.02822319, -0.83957549, -0.33771694, -0.08184963], [-0.03148106, -0.97819034, -1.85828013, -0.33782379]])
注意:直接調用數組的方法的排序將直接改變數組而不會產生新的拷貝。
矩陣運算:
In [62]: x=np.arange(9).reshape(3,3) In [63]: x Out[63]: array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) In [64]: np.dot(x,x) # 矩陣相乘 Out[64]: array([[ 15, 18, 21], [ 42, 54, 66], [ 69, 90, 111]]) In [65]: x.T # 矩陣轉置 Out[65]: array([[0, 3, 6], [1, 4, 7], [2, 5, 8]])
在numpy中的linalg中有還有不少矩陣運算,好比svd分解,qr分解,cholesky分解等等。
numpy數據的讀取和保存:
In [68]: np.save('name',data) In [69]: np.load('name.npy') Out[69]: array([[-0.03148106, -0.97819034, -1.85828013, -0.33782379], [-0.02822319, -0.83957549, -0.33771694, -0.08184963], [ 1.58669867, -0.31934723, 0.51126626, 0.80444954], [ 1.68160714, 1.57692769, 0.70764701, 1.17201164]])