本文是一個關於Python numpy的基礎學習教程,其中,Python版本爲Python 3.x
python
Numpy = Numerical + Python,它是Python中科學計算的核心庫,能夠高效的處理多維數組的計算。而且,由於它的許多底層函數是用C語言編寫的,因此運算速度敲快。數組
NumPy的主要對象是同類型的多維數組ndarray。它是一個通用的同構數據多維容器,全部的元素必須是相同類型的,並經過正整數元組索引。利用該對象能夠對整塊數據執行一些數學運算,語法和標量元素之間的運算同樣。在NumPy中,維度稱爲軸,軸的數目爲rank。dom
介紹一下ndarray經常使用的屬性:函數
建立數組一般有5種方式:性能
1. 由Python結構(list, tuple等)轉換學習
建立數組最簡單的辦法就是使用array對象,它能夠接受任何序列型的對象,而後產生一個新的含有傳入數據的numpy數組(ndarray)。
舉個最簡單的例子:測試
import numpy as np a = np.array([1, 2, 3]) print(a) print(a.dtype) print(a.shape)
2. 使用Numpy原生數組建立(arange, ones,zeros等)大數據
如:設計
b = np.zeros(10) c = np.ones((1, 2))
3. 從磁盤讀取數組code
使用np.load方法讀取數據。
4. 使用字符串或緩衝區從原始字節建立數組
5. 使用特殊庫函數(random等)
一維數組中的索引表面看起來和Python list的功能差很少。
對於切片而言,當你將一個標量值賦值給一個切片時,該值會自動傳播到整個選區,跟Python list最重要的區別在於:Numpy中數組的切片做用的是原始數據的視圖,也就是數據沒有被複制,全部的修改都會直接做用到源數據。這是由於,Numpy設計之初就是爲了處理大數據,將數據複製來複制去天然會產生不少性能問題。若是你想要獲得一份數據副本,就須要顯式的使用.copy()方法。
舉個例子:
arr = np.arange(10) print(arr) print(arr[0]) print(arr[1:6]) arr_slice = arr[1:6] arr_slice[1:3] = 5 print(arr_slice) print(arr) arr_copy = arr[1:6].copy() arr_copy[1:3] = 6 print(arr_copy) print(arr)
對於多維數組,各索引位置上的元素再也不是標量,而是數組,能夠傳入一個以逗號隔開的索引列表來訪問單個元素。其它操做和一維數組相同。
舉個例子:
arr_2d = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) print(arr_2d[0]) print(arr_2d[0, 1]) arr_2d_slice = arr_2d[1] print(arr_2d_slice) arr_2d_slice[0] = 1 print(arr_2d_slice) print(arr_2d)
ndarray的切片語法和Python list相似,對於高維對象,花樣比較多,能夠在一個或者多個軸進行切片,也能夠跟整數索引混合使用(下降維度)。
舉個例子:
arr_test = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) print(arr_test[:2]) print(arr_test[:2, 1:]) print(arr_test[1, :1]) arr_slice_test = arr_test[:2, 1:] arr_slice_test[0] = 0 print( arr_slice_test) print(arr_test)
布爾型索引
經過布爾型索引,能夠方便咱們根據指定條件快速的檢索數組中的元素。若是進行變量或者標定量的大數據處理,這種篩選功能的使用確定會給程序的設計帶來極大的便捷。
舉個簡單例子:
In [1]: import numpy as np In [2]: x = np.array([[0, 1], [2, 3], [3, 4]]) In [3]: x Out[3]: array([[0, 1], [2, 3], [3, 4]]) In [4]: x > 2 Out[4]: array([[False, False], [False, True], [ True, True]]) In [5]: x[ x > 2] = 0 In [6]: x Out[6]: array([[0, 1], [2, 0], [0, 0]])
而且,能夠結合使用ndarray的統計方法來對布爾型數組中的True值進行計數,常見有三種方法:
花式索引
花式索引(Fancy indexing)是一個Numpy的術語,指的是利用整數數組進行索引。
花式索引根據索引數組的值做爲目標數組的某個軸的下標來取值。對於使用一維整型數組做爲索引,若是目標是一維數組,那麼索引的結果就是對應位置的元素;若是目標是二維數組,那麼就是對應下標的行。
花式索引跟切片不同,它老是將數據複製到新數組中。
舉個例子:
In [1]: import numpy as np In [2]: array = np.empty((4, 3)) In [3]: for i in range(4): ...: array[i] = i ...: In [4]: array Out[4]: array([[0., 0., 0.], [1., 1., 1.], [2., 2., 2.], [3., 3., 3.]]) In [5]: array[[1, 3]] Out[5]: array([[1., 1., 1.], [3., 3., 3.]]) In [6]: array[[-1, -3]] Out[6]: array([[3., 3., 3.], [1., 1., 1.]]) In [7]: array[np.ix_([3, 0],[2, 1])] Out[7]: array([[3., 3.], [0., 0.]])
形狀轉換
介紹幾個常見的修改數組形狀的方法:
reshape():不改變原始數據的狀況下修改數組
flat():一個數組元素的迭代器,能夠處理數組元素中的每一個數據
flatten():返回一份數組拷貝,對拷貝所作的處理不會影響原始數組,格式爲.flatten(order=''),其中order='C'表示按行展開,'F'表示按列,'A'表示原順序,'K'表示元素在內存中的出現順序。
ravel():展平的數組元素,順序一般是"C風格",返回的是數組視圖,修改會影響原始數組。
該函數接收兩個參數:
舉個例子:
arr = np.arange(12) print(arr) arr1 = arr.reshape(3, 4) for item in arr1: print(item) for item in arr1.flat: print(item) print(arr1.flatten()) print(arr1.flatten(order="K")) arr.flatten()[10] = 0 print(arr) print(arr.ravel()) arr.ravel()[10] = 0 print(arr)
轉置與軸對換
介紹常見的幾種方法:
轉置是數據重塑的一種特殊形式,返回了源數據的視圖。簡單的轉置可使用.T,也可使用transpose方法和swapaxes。
舉個例子:
arr = np.arange(12).reshape((2, 2, 3)) print(arr) print(arr.T) print(arr.transpose((1, 0, 2))) print(arr.swapaxes(1, 2))
通用函數(ufunc)是一種對ndarray中的數據執行元素級運算的函數,可將其分爲一元和二元進行說明。
一元func
一元func可看作是簡單的元素級變體,好比sqrt和cos,舉個例子:
arr = np.arange(10) print(np.sqrt(arr)) print(np.square(arr))
二元func
接受2個數組,而後返回一個結果數組,好比add和mod,舉個例子:
arr1 = np.arange(10) arr2 = np.arange(10) print(np.add(arr1, arr2))
更多函數去官方文檔查閱,哈哈,這裏就不贅述了。
基礎運算
在Numpy中,能夠利用ndarray對整塊數據執行一些數學運算,語法和普通的標量元素之間的運算同樣。其中,數組與標量的運算會將標量做用於各個數組元素。
舉個例子:
i = np.array([[1, 2], [3, 4]]) j = np.array([[5, 6], [7, 8]]) print(i + j) print(i - j) print(i - 1) print(i * j) print( i / j)
以上,乘法並不一樣於矩陣乘法,若需進行矩陣相乘,可以使用:
i = np.array([[1, 2], [3, 4]]) j = np.array([[5, 6], [7, 8]]) print(j.dot(i))
除此以外,Numpy還提供瞭如下經常使用統計方法:
數組表達式
編寫數組表達式處理多個數組數據也是很便捷高效的,舉個例子:假設咱們想要在一組值(網格型)上計算函數sqrt(x^2 + y^2),使用np.mashgrid函數接受兩個一維數組,產生兩個二維矩陣:
In [1]: import numpy as np In [2]: points = np.arange(-5, 5, 0.01) In [3]: x, y = np.meshgrid(points, points) In [4]: x Out[4]: array([[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99], [-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99], [-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99], ..., [-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99], [-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99], [-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99]]) In [5]: z = np.sqrt(x ** 2 + y ** 2) In [6]: z Out[6]: array([[7.07106781, 7.06400028, 7.05693985, ..., 7.04988652, 7.05693985, 7.06400028], [7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815, 7.05692568], [7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354, 7.04985815], ..., [7.04988652, 7.04279774, 7.03571603, ..., 7.0286414 , 7.03571603, 7.04279774], [7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354, 7.04985815], [7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815, 7.05692568]])
條件篩選
介紹幾個常見的篩選方法:
接下來,使用Numpy來模擬隨機漫步操做下數組運算。
首先,實現一個很簡單的1000步的隨機漫步,從0開始,隨機生成1和-1,判斷隨機漫步過程當中第一次到達某個值(暫定爲8)的時間(步數),實現:
import numpy as np nsteps = 1000 draws = np.random.randint(0, 2, size=nsteps) steps = np.where(draws > 0, 1, -1) # 各步的累計和 walk = steps.cumsum() # 第一次到達8的時間 walk_8 = (np.abs(walk) >= 8).argmax() print(walk_8)