1. 程式人生 > >Numpy學習筆記(更新中)

Numpy學習筆記(更新中)

一個在Python中做科學計算的基礎庫,重在數值計算,也是大部分PYTHON科學計算庫的基礎庫,多用於在大型、多維陣列上執行數值運算。

陣列的定義

import numpy as np
# numpy陣列的定義方法
a = np.arange(1, 62)
b = np.array([1, 3, 5])
c = np.array(range(1, 62))

# 這樣產生的a,b,c三個結果是一樣的,均為[1, 3, 5]
# 這裡看一下陣列的型別和陣列元素的型別的定義和修改,type(a)表示的是陣列a的型別,a.dtype則表示的是陣列a中元素的型別。
In [1
]: import numpy as np In [2]: a = np.array([1, 2, 3]) In [3]: print(a, type(a), a.dtype) [1 2 3] <class 'numpy.ndarray'> int32 In [4]: a = np.array([1, 2, 3], dtype = "float64") In [5]: print(a, type(a), a.dtype) [1. 2. 3.] <class 'numpy.ndarray'> float64 In [6]: a = a.astype("int64"
) In [7]: print(a, type(a), a.dtype) [1 2 3] <class 'numpy.ndarray'> int64 #要保留固定位數的小數需要用到np.round() In [1]: import random In [2]: import numpy as np In [3]: "%.2f"%random.random() Out[3]: '0.56' In [4]: round(random.random(), 2) Out[4]: 0.73 In [5]: a = np.round(np.array([random.random() for
i in range(10)]), 2) In [6]: a Out[6]: array([0.7 , 0.95, 0.6 , 0.03, 0.27, 0.96, 0.17, 0.48, 0.3 , 0.23]) In [7]: np.round(a, 1) Out[7]: array([0.7, 1. , 0.6, 0. , 0.3, 1. , 0.2, 0.5, 0.3, 0.2])

陣列的形狀

以下的程式碼是在Jupyter Notebook中完成的:

# 陣列的形狀
In [1]: import numpy as np
In [2]: a = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
In [3]: a
Out[3]: array([[[ 1, 2, 3],
                [ 4, 5, 6]],
                [[ 7, 8, 9],
                [10, 11, 12]]])
In [4]: a.shape
Out[4]: (2, 2, 3)
# 上面元組中的元素個數即是這個陣列的維數,例如這個就是個三維陣列,他一共有 2 塊,每塊有 2 行, 3 列,即(2, 2, 3)
In [5]: a.reshape((3, 4))
Out[5]: array([[ 1, 2, 3, 4],
               [ 5, 6, 7, 8],
               [ 9, 10, 11, 12]])
In [6]: a.reshape((12,))
Out[6]: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
In [7]: a
Out[7]: array([[[ 1, 2, 3],
                [ 4, 5, 6]],
                [[ 7, 8, 9],
                [10, 11, 12]]])
# 從這裡看以看出a.reshape並不能改變a的形狀和維度,如果需要改變a的維度和形狀,需要重新對a進行賦值,如下?
In [8]: a = a.reshape((4,3))
In [9]: a
Out[9]: array([[ 1, 2, 3],
               [ 4, 5, 6],
               [ 7, 8, 9],
               [10, 11, 12]])
# 計算一個二維陣列的元素個數,可以使用如下的方法,shape[0]是這個二維陣列的行數,shape[1]即是這個陣列的列數。
In [10]: a.shape[0] * a.shape[1]
Out[10]: 12
# 所以將一個二維陣列變為一維陣列便有了如下的方法:
In [11]: a = a.reshape((a.shape[0] * a.shape[1],))
In [12]: a
Out[12]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])
# 當然一個現成簡單的方法是使用flatten這個函式
In [13]: a.flatten()
Out[13]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

陣列的計算

# 陣列直接對一個數進行加減乘除,產生的結果是陣列中的每個元素都會加減乘除這個數。
In [14]: a * 2
Out[14]: array([[ 2, 4, 6],
                [ 8, 10, 12],
                [14, 16, 18],
                [20, 22, 24]])
In [15]: a / 0
    D:\Anaconda3\lib\site-packages\ipykernel\__main__.py:1: RuntimeWarning: divide by zero           encountered in true_divide
      if __name__ == '__main__':
Out[15]: array([[inf, inf, inf],
                [inf, inf, inf],
                [inf, inf, inf],
                [inf, inf, inf]])
# 接下來我們看一下陣列與陣列之間的計算
In [17]: b = np.arange(12,24).reshape((4,3))
In [18]: b
Out[18]: array([[12, 13, 14],
                [15, 16, 17],
                [18, 19, 20],
                [21, 22, 23]])
In [19]: a + b
Out[19]: array([[13, 15, 17],
                [19, 21, 23],
                [25, 27, 29],
                [31, 33, 35]])
In [20]: c = np.array([1,2,3])
In [21]: a+c
Out[21]: array([[ 2, 4, 6],
                [ 5, 7, 9],
                [ 8, 10, 12],
                [11, 13, 15]])
In [22]: d = np.arange(10,14).reshape((4,1))
In [23]: d
Out[23]: array([[10],
                [11],
                [12],
                [13]])
In [24]: a + d
Out[24]: array([[11, 12, 13],
                [15, 16, 17],
                [19, 20, 21],
                [23, 24, 25]])
# 從上面可以看出,和線性代數中不同的是,m*n列的m行的一維陣列或者n列的一維陣列也是可以計算的。

這是為什麼呢?這裡要提到numpy的廣播原則:

如果兩個陣列的後緣維度(從末尾開始算起的維度)軸長度相符其中一方的長度為1,則認為它們是廣播相容的。廣播會在缺失維度和(或)軸長度為1的維度上進行。

在上面的程式碼中,a的維度是(4,3),c的維度是(1,3);d的維度是(4,1)。所以假設有兩個陣列,第一個的維度是(x_1, y_1, z_1),另一個數組的維度是(x_2, y_2, z_2),要判斷這兩個陣列能不能進行計算,可以用如下方法來判斷:

if z_1 == z_2 or z_1 == 1 or z_2 == 1:
    if y_1 == y_2 or y_1 == 1 or y_2 == 1:
        if x_1 == x_2 or x_1 == 1 or x_2 == 1:
            可以運算
        else:
            不可以運算
    else:
        不可以運算
else:
    不可以運算

這裡需要注意:(3,3,2)和(3,2)是可以運算的,因為對於二維陣列(3,2)也可以表示為(1,3,2),套用上述的規則是完全適用的,同理:(4,2,5,4)和(2,1,4)也是可以進行運算的。

軸(axis)

在numpy中可以理解為方向,使用0,1,2…數字表示,對於一個一維陣列,只有一個0軸,對於2維陣列(shape(2,2)),有0軸和1軸,對於三維陣列(shape(2,2, 3)),有0,1,2軸。

二維陣列的軸如下圖所示:

2維陣列的軸

三維陣列的軸:

3維陣列的軸

numpy讀資料

使用如下語句來讀取CSV檔案:np.loadtxt(fname,dtype=np.float,delimiter=None,skiprows=0,usecols=None,unpack=False) 引數含義

陣列轉置:(兩種方法)

  • .transpose()
  • .swapaxes(1, 0)

取陣列中的值

import numpy as np

us_file_path = "./youtube_video_data/US_video_data_numbers.csv"
uk_file_path = ".\youtube_video_data\GB_video_data_numbers.csv"

t1 = np.loadtxt(us_file_path, delimiter=",", dtype="int64")
print(t1)

print("*" * 100)
# 取行
# print(t1[2])
# print(t1[2,])

# 取連續的多行
# print(t1[2:])
# print(t1[2: ,])

# 取不連續的多行
# print(t1[[2, 9, 3]])
# print(t1[[2, 9, 3],])

# 取列
# print(t1[:,2])

# 取連續的多列
# print(t1[:,2:])

# 取不連續的多列
# print(t1[:, [0, 2]])

# 取元素
# print(t1[1, 3])

# 取連續多行和多列
# print(t1[1:4, 1:4])

# 取多個不相鄰的點(0,1), (2, 2), (2, 3)
# print(t1[[0, 1, 2], [2, 2, 3]])

numpy中數值修改

# 取值然後賦值即可
In [1]: import numpy as np

In [2]: t2 = np.arange(24).reshape(4, 6)

In [3]: t2
Out[3]:
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])

In [4]: t2<10
Out[4]:
array([[ True,  True,  True,  True,  True,  True],
       [ True,  True,  True,  True, False, False],
       [False, False, False, False, False, False],
       [False, False, False, False, False, False]])

In [5]: t2[t2<10] = 3

In [6]: t2
Out[6]:
array([[ 3,  3,  3,  3,  3,  3],
       [ 3,  3,  3,  3, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])

In [7]: np.where(t2<10, 0, 10)
Out[7]:
array([[ 0,  0,  0,  0,  0,  0],
       [ 0,  0,  0,  0, 10, 10],
       [10, 10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10, 10]])

clip操作

t.clip(10, 12)
# 這句話的意思是將陣列t中小於10的數變為10,大於12的數變為12

拼接操作和換行換列操作

In [12]: a = np.arange(12).reshape(4,3)

In [13]: b = np.arange(12,24).reshape(4,3)

In [14]: a
Out[14]:
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

In [15]: b
Out[15]:
array([[12, 13, 14],
       [15, 16, 17],
       [18, 19, 20],
       [21, 22, 23]])
# 豎直拼接
In [17]: np.vstack((a,b))
Out[17]:
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14],
       [15, 16, 17],
       [18, 19, 20],
       [21, 22, 23]])
# 水平拼接
In [18]: np.hstack((a,b))
Out[18]:
array([[ 0,  1,  2, 12, 13, 14],
       [ 3,  4,  5, 15, 16, 17],
       [ 6,  7,  8, 18, 19, 20],
       [ 9, 10, 11, 21, 22, 23]])

# 兩行互換
Out[21]: 0

In [22]: a[[0,1],:] = a[[1,0],:]

In [23]: a
Out[23]:
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])   

將一維行向量轉置為一維列向量的辦法.reshape(-1, 1)

構造全為0或1的包含n個元素的一維向量的方法:

# 列向量
np.zeros((n, 1))
np.ones((n, 1))
# 行向量
np.zeros((1, n))
np.ones((1, n))