Numpy(Numerical Python)是一個開源的Python科學計算庫。python
在使用以前咱們須要引入庫。 編程
import numpy
這個庫的功能經過它的圖標咱們就能夠看出一二來,就是用來進行矩陣運算的。矩陣咱們常見的形式是一維數組(好比:[1, 2, 3])和二維數組(好比:[[1, 2, 3], [4, 5, 6], [7, 8, 9]])。咱們能夠經過Numpy中的array函數來將列表轉換爲Numpy中使用的矩陣,好比: 數組
import numpy as np num = [[1, 2, 3], [4, 5, 6]] print(num) print(type(num)) arr_num = np.array(num) print(arr_num) print(type(arr_num)) """ 運行結果: [[1, 2, 3], [4, 5, 6]] <class 'list'> [[1 2 3] [4 5 6]] <class 'numpy.ndarray'> """
讓咱們從上面的運行結果來分析一下:dom
那麼分析的結果呢,就是轉換以後數據確實發生了改變,具體發生了什麼改變,後面會進行介紹。函數
這裏咱們要認識到numpy的兩個特色:性能
咱們說過ndarray對象是Numpy的核心。那麼它的好處有哪些呢?學習
(1)底層處理大數據
首先,它最大的特色就是與Python底層處理方式的區別。在數據存儲中,有兩種爲人熟知的存儲結構,一個是數組,一個是鏈式。它們二者都有各自的好處,由於數組是連續空間因此在數據讀寫上很快,而在插入和刪除時就很慢了;鏈式由於指針的緣由能夠很方便的找到上下關係,這讓插入和刪除變得簡單不少。ndarray和Python的底層就很像這種關係。ui
當咱們用ndarray存儲數據的時候,全部的元素都是相同數據類型,地址也是連續的。spa
在Python中,是經過尋址找到下一個元素的位置的。
在編程領域中,簡單的代價就是效率的提升。ndarray雖然在通用性上比Python差,可是隨之帶來的是性能的提高。Numpy是用於科學計算的庫,因此它會面臨大量的數值計算,這樣的設計可讓咱們用更短的時間計算出咱們須要的結果。
下面是一個例子,分別用Python和Numpy計算一段數據的和。
從上面兩個數據咱們就能夠看出二者的計算速度對比了,若是數據量再提高,咱們就更可以看到二者的速度差別了,這裏就再也不作實驗。
(2)ndarray支持並行化運行
學習Python的人應該知道,在Python中有GIL鎖這個東西,它讓咱們在一個進程中不管開多少個線程在當前時刻都只能有一個線程訪問CPU。Numpy底層使用C語言編寫,內部解除了這個限制,讓它的效率遠高於純Python代碼。
咱們在建立矩陣的時候,能夠指定數據的類型。好比:
若是咱們沒有指定數據類型,整數默認int64,小數默認float64。
ndarray.shape # 數組維度的元組
ndarray.ndim # 數組維數
ndarray.size # 數組中的元素數量
ndarray.itemsize # 一個數組元素的長度(字節)
ndarray.dtype # 數組元素的類型
示例:
numpy.linspace() # 在一個範圍取平均分佈的值,好比:numpy.linspace(2, 50, 100),在範圍爲2到50的閉區間中生成100個平均分佈的值。
import numpy as np # 方式1:使用genfromtxt函數讀取文件
f = np.genfromtxt("file.csv", delimiter="數據的分隔符", dtype=str) # 第一個參數是讀取的文件名,第二個參數是讀取文件中數據分隔符,第三個參數表示以什麼類型讀入數據。
# 方式2:使用array函數將列表轉換爲矩陣
arr_num1 = np.array([[1, 2, 3], [4, 5, 6]]) # 方式3:使用zeros函數建立一個初始化矩陣
arr_num2 = np.zeros((3, 4)) # 生成一個三行四列的矩陣,初始值爲0
# 方式4:使用ones函數建立一個初始化矩陣
arr_num3 = np.ones((3, 4)) # 生成一個三行四列的矩陣,初始值爲1
# 方式5:使用empty函數建立一個初始化矩陣
arr_num4 = np.empty((3, 4), dtype=np.float16) # 生成一個三行四列的矩陣,初始值爲爲一些接近於0的數字。
# 方式6:使用arange函數建立參數範圍內的矩陣。
arr_num5 = np.arange(10, 20, 2) # 生成區間爲[10, 20),步長爲2的列表:[10 12 14 16 18]
arr_num6 = np.arange(10) # 生成:[0 1 2 3 4 5 6 7 8 9]
# 方式7:將給定範圍分紅多少段,而後生成矩陣。
arr_num7 = np.linspace(1, 10, 20) # 將範圍爲[1, 10]的數字分爲20段。
# 方式8:使用random.random函數生成一個矩陣,值的範圍爲0到1之間的數字。
arr_num8 = np.random.random((100, 200))
當咱們使用numpy.array()建立的時候,裏面數據格式必須是一致的。若是數組中有整數和浮點數的話,爲了知足浮點數的存儲要求,全部的整數也都會轉成浮點數來進行存儲。
import numpy as np num1 = np.array([10, 20, 30, 40]) num2 = np.arange(4) print(num1, num2) num3 = num1 - num2 print("運行結果爲:", num3) """ 運行結果 [10 20 30 40] [0 1 2 3] 運行結果爲: [10 19 28 37] """
如上面例子中所示,
當咱們對矩陣進行算數運算的時候,都是對整個矩陣中的元素逐個計算;多個矩陣運算時,對應矩陣元素進行計算。
這裏還須要知道,若是不是一維矩陣的計算,而是二維的計算,是什麼狀況?
好比:
import numpy as np num = np.arange(4).reshape(2, 2) print("-------num-------") print(num) print("-------num*2-----") print(2*num) print("-------矩陣*矩陣------") print("num1:") num1 = np.arange(5, 9).reshape(2, 2) print(num1) print("-----") print(num*num1) print("-----使用dot函數-------") print(np.dot(num, num1)) """ 運行結果爲: -------num------- [[0 1] [2 3]] -------num*2----- [[0 2] [4 6]] -------矩陣*矩陣------ num1: [[5 6] [7 8]] ----- [[ 0 6] [14 24]] -----使用dot函數------- [[ 7 8] [31 36]] """
在上面例子中,矩陣*矩陣很容易看出來,就是兩個矩陣對應位置數據進行乘法而後放到對應的位置。當咱們使用dot函數的時候,最簡單理解就是:矩陣中,該數據所在行的數據和該數據所在列的數據對應位置相乘結果再把結果相加,最後放到這個數據的位置就能夠了,好比上面例子中:0*5+1*7=7;0*6+1*8=8;2*5+3*7=31;2*6+3*8=36。
上面np.dot(a, b)還能夠寫成a.dot(b)這樣的形式。
import numpy as np num = np.arange(4) print(np.sin(num)) print(np.cos(num)) print(np.tan(num)) print(np.exp(num)) # 表示e的多少次冪
print(np.sqrt(num)) # 表示參數的平方根得數
print(np.floor(num)) # 元素向下取整
import numpy as np num = np.arange(4) print(num) # [0 1 2 3]
print(num > 2) # [False False False True]
print(num == 3) # [False False False True]
數組排序時使用的方法,其中: kind=′quicksort′kind=′quicksort′爲快排;kind=′mergesort′kind=′mergesort′爲混排;kind=′heapsort′kind=′heapsort′爲堆排;
在使用的時候,咱們還能夠進行不一樣維度的求和。設置的方法是使用參數axis,當它的值爲0的時候,對每一行的數字進行統計,當它的值爲1的時候,對每一列的數據進行統計,好比:
import numpy as np num = np.arange(12).reshape(3, 4) print(num) print("--------") print("矩陣中最小值:", np.min(num)) print("矩陣中每列最大值:", np.max(num, axis=0)) print("矩陣中每行最小值", np.min(num, axis=1)) print("矩陣參數的平均值(方式1)", np.mean(num)) print("矩陣參數的平均值(方式2)", np.average(num, axis=0)) print("矩陣中最大值索引位置:", np.argmax(num)) print("矩陣中每列最大值索引位置:", np.argmax(num, axis=1)) print("矩陣中中間數據是多少:", np.median(num, axis=1)) # 同上,若是忽略axis參數,則爲整個矩陣的中間數字。
print("矩陣數據斐波那契數列方式相加:", np.cumsum(num)) print("返回兩個array,一個存放行座標,一個存放列座標:", np.nonzero(num)) # 能夠用切片分別取出array。
print("矩陣中,逐行降序排列:") print(-1*np.sort(-num)) # 默認升序排列,也能夠用這種方式變成降序排列。
print("矩陣反向") print(num.T) print("指定參數的替換:") print(np.clip(num, 3, 6.5)) print("將多維矩陣變成一維矩陣:", np.ravel(num)) """ 運行結果: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] -------- 矩陣中最小值: 0 矩陣中每列最大值: [ 8 9 10 11] 矩陣中每行最小值 [0 4 8] 矩陣參數的平均值(方式1) 5.5 矩陣參數的平均值(方式2) [4. 5. 6. 7.] 矩陣中最大值索引位置: 11 矩陣中每列最大值索引位置: [3 3 3] 矩陣中中間數據是多少: [1.5 5.5 9.5] 矩陣數據斐波那契數列方式相加: [ 0 1 3 6 10 15 21 28 36 45 55 66] 返回兩個array,一個存放行座標,一個存放列座標: (array([0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], dtype=int64), array([1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], dtype=int64)) 矩陣中,逐行降序排列: [[ 3 2 1 0] [ 7 6 5 4] [11 10 9 8]] 矩陣反向 [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]] 指定參數的替換: [[3. 3. 3. 3. ] [4. 5. 6. 6.5] [6.5 6.5 6.5 6.5]] 將多維矩陣變成一維矩陣: [ 0 1 2 3 4 5 6 7 8 9 10 11] """
在python的中,咱們能夠經過索引來讀取列表中的數據。在ndarray中,咱們也能夠用索引來進行矩陣中數據的讀取。
當咱們使用索引取值的時候,也能夠用切片的語法,numpy中的切片也和python同樣,切片取值是左閉右開區間。好比:1:3取到的數據爲[1, 3)區間。
import numpy as np arr1 = np.arange(10) print(arr1) print("索引取一維數組中的數:") print(arr1[3]) print("---------------") arr2 = np.arange(12).reshape(3, 4) print(arr2) print("索引取二維數組中的數:") print(arr2[1][2]) print(arr2[1, 2]) print(arr2[2, :]) # 打印第三行的全部數
print(arr2[:, 2]) # 打印第三列的全部數
print(arr2[1, 1:2]) # 打印第二行的第二個數
print("---------------") print("迭代讀取每一行:") for row in arr2: print(row) print("---------------") print("迭代讀取每一列:") for col in arr2.T: print(col) print("---------------") print("迭代方式讀取每個元素:") print(arr.flatten()) # flat返回的是一個迭代器,它的內容爲咱們能夠用這個flatten函數來看。
for item in arr.flat: print(item) """ 運行結果爲: [0 1 2 3 4 5 6 7 8 9] 索引取一維數組中的數: 3 --------------- [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] 索引取二維數組中的數: 6 6 [ 8 9 10 11] [ 2 6 10] [5] --------------- 迭代讀取每一行: [0 1 2 3] [4 5 6 7] [ 8 9 10 11] --------------- 迭代讀取每一列: [0 4 8] [1 5 9] [ 2 6 10] [ 3 7 11] --------------- 迭代方式讀取每個元素: [ 0 1 2 3 4 5 6 7 8 9 10 11] 0 1 2 3 4 5 6 7 8 9 10 11 """
import numpy as np arr1 = np.arange(10, 20).reshape(2, 5) arr2 = np.arange(20, 30).reshape(2, 5) print("打印矩陣arr1:") print(arr1) print("打印矩陣arr2:") print(arr2) print() print("----縱向合併------") print(np.vstack((arr1, arr2))) print("----橫向合併------") print(np.hstack((arr1, arr2))) """ 運行結果: 打印矩陣arr1: [[10 11 12 13 14] [15 16 17 18 19]] 打印矩陣arr2: [[20 21 22 23 24] [25 26 27 28 29]] ----縱向合併------ [[10 11 12 13 14] [15 16 17 18 19] [20 21 22 23 24] [25 26 27 28 29]] ----橫向合併------ [[10 11 12 13 14 20 21 22 23 24] [15 16 17 18 19 25 26 27 28 29]] """
注意分割的時候,要保證邏輯上的正確,好比:我要分割行,一共有三行,我要分爲兩個部分,這個時候就會報錯。
import numpy as np arr = np.arange(8).reshape(2, 4) print("打印矩陣arr1:") print(arr) print() print("----橫向分割------") print(np.vsplit(arr, 2)) print("----縱向分割------") print(np.hsplit(arr, 2)) print("----使用split進行數據分割-----") print(np.split(arr, 2,axis=1)) """ 運行結果: 打印矩陣arr1: [[0 1 2 3] [4 5 6 7]] ----橫向分割------ [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]])] ----縱向分割------ [array([[0, 1], [4, 5]]), array([[2, 3], [6, 7]])] ----使用split進行數據分割----- [array([[0, 1], [4, 5]]), array([[2, 3], [6, 7]])] """
矩陣的拷貝並不像python中同樣,有深拷貝和淺拷貝之分,複製了以後,它們操做的都是同樣的數據。那咱們只想要複製怎麼辦呢?這就要用到專門的函數來copy了。
import numpy as np arr1 = np.arange(10) arr2 = arr1 print(arr1 is arr2) arr3 = arr1.copy() print(arr1 is arr3) """ 運行結果: True False """