1. 程式人生 > >1. Jupyter Notebook、numpy的使用

1. Jupyter Notebook、numpy的使用

一. Jupter Notebook中的魔法方法

%run的使用

  • 載入不在專案包中的檔案
  • 專案中的包不使用%run, 使用python的import語法即可
1. %run  myscript/hello.py

2. hello("balabala")      # 這樣就可以直接呼叫hello.py中的函數了

%timeit的使用

  • 會先自動 把程式重複執行一定次數, 程式執行時間太短就會迴圈更多次
  • 通過找到最快的3次迴圈, 得到程式執行的時間
1. %timeit  L = [i**2 for i in range(1000)]

結果:  1000 loops, best of 3: 515 µs per  loop

%time的使用

  • 不會把程式重複執行, 只執行一次得到程式的執行時間
  • cputime是計算機cpu和sys 計算所用時間的和
  • walltime是現實世界流逝的時間
  • 得到的時間是不穩定的
  • 在只需要知道大概的時間或者程式執行時間太長, 適用
1. %time L = [i**2 for i in range(1000)]

結果:  CPU times: user 452 µs, sys: 17 µs, total: 469 µs
       Wall time: 536 µs

如果想要測試整段程式碼, 可以使用%%

  • 舉例
%%time
for e in [1,2,3,4,6]:
  print(e)


二. Numpy資料基礎

np.array的使用

1. import numpy as np
2. nparr = np.array([i for i in range(10)])
3. nparr

out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])


1. nparr[5]
out: 5


1. nparr[5]=100.0
2. nparr[5]
out: 100  

1. nparr.dtype
out: dtype('int64')     # 之前的100.0被 隱式地型別轉換了

三. 建立Numpy陣列和矩陣

  • 建立全零矩陣
1. np.zeros(10)    # 預設是浮點數型別
out: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

2. np.zeros(10, dtype=int)    # 可以指定為 int 型別
out: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

3. np.zeros((3,5))     # 傳入元組 表示維度
out:array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])

4. np.zeros(shape=(3,5), dtype=int)   # 3中其實省略了shape
out:array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]])
  • 建立全一矩陣
1. np.ones((3,5))    # 用法和zeros一樣
out: array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])
  • 建立全部都為指定值的矩陣
1. np.full((3,5), 666)    # 省略了引數名 np.full(shape=(3,5), full_value=666)
out:array([[666, 666, 666, 666, 666],
       [666, 666, 666, 666, 666],
       [666, 666, 666, 666, 666]])



# 這裡 full_value是 666, out就會是int型, 如果給的是666.0, out就會是浮點型
  • np.arrange
1. np.arange(0,1,0.2)
out: array([0. , 0.2, 0.4, 0.6, 0.8])

# np.arange使用方法和python基礎語法range一樣, 得到前閉後開的資料集
# 但np.arange步長可以是浮點數, 二range只能是整數
  • np.linspace
1. np.linspace(0,20,10)
out:array([ 0.        ,  2.22222222,  4.44444444,  6.66666667,  8.88888889,
       11.11111111, 13.33333333, 15.55555556, 17.77777778, 20.        ])

# linspace  第三個引數是 得到的資料個數, 而非步長
  • np.random.randint
1. np.random.randint(0, 10, 10)   # 生成10個 0~10的隨機數, 組成的向量
out:array([1, 8, 1, 4, 6, 8, 7, 1, 7, 1])


2. np.random.randint(4,8,size=(3,5))   # 生成3x5的隨機矩陣
out:array([[7, 5, 4, 5, 5],
       [4, 6, 7, 6, 5],
       [5, 6, 6, 6, 7]])
       
3. np.random.seed(666)  # 指定隨機種子
4. np.random.randint((4,8, size=(3,5))
out:array([[4, 6, 5, 6, 6],
       [6, 5, 6, 4, 5],
       [7, 6, 7, 4, 7]])

5. np.random.randint((4,8, size=(3,5))   # 在指定了隨機種子後, 會生成一樣的隨機矩陣
out:array([[4, 6, 5, 6, 6],
       [6, 5, 6, 4, 5],
       [7, 6, 7, 4, 7]])
       

# 除錯時, 希望重現 一樣的隨機矩陣, 這時需要用到np.random.seed

  • np.random.random
1. np.random.random()   # 生成0~1的 隨機浮點數
out:0.2811684913927954

2. np.random.random(10)
out:array([0.46284169, 0.23340091, 0.76706421, 0.81995656, 0.39747625,
       0.31644109, 0.15551206, 0.73460987, 0.73159555, 0.8578588 ])

3. np.random.random((3,5))
out:array([[0.76741234, 0.95323137, 0.29097383, 0.84778197, 0.3497619 ],
       [0.92389692, 0.29489453, 0.52438061, 0.94253896, 0.07473949],
       [0.27646251, 0.4675855 , 0.31581532, 0.39016259, 0.26832981]])

4. np.random.normal()      # 符合正態分佈,均值為0 , 方差為1 的隨機浮點數 
out:0.7760516793129695


5. np.random.normal(10,100)    # 指定均值為10, 方差為100 
out:128.06359754812632


6. np.random.normal(0,1, (3,5))      # 均值0 方差1  size為3x5
out:array([[ 0.06102404,  1.07856138, -0.79783572,  1.1701326 ,  0.1121217 ],
       [ 0.03185388, -0.19206285,  0.78611284, -1.69046314, -0.98873907],
       [ 0.31398563,  0.39638567,  0.57656584, -0.07019407,  0.91250436]])

當對函式的引數不清楚時, 使用?

1. np.random.normal?   # 帶上?  就會跳出 對應的文件

Docstring:
normal(loc=0.0, scale=1.0, size=None)   # loc均值   scale方差

Draw random samples from a normal (Gaussian) distribution.

The probability density function of the normal distribution, first
derived by De Moivre and 200 years later by both Gauss and Laplace
independently [2]_, is often called the bell curve because of
its characteristic shape (see the example below)............



2. help(np.random.normal)    
# 和使用?, 效果類似, 
# 但? 是為跳出一個小頁面的說明文件
# help  會把說明文件 放在 out: 後面

四. Numpy陣列和矩陣的基本操作

屬性

In:x1 = np.arange(10)
In:x2 = np.arange(15).reshape(3,5)

In:x1.ndim
out: 1     # ndim表示矩陣 的維度

In:x2.ndim
out: 2


In:x1.shape
out: (10,)      # shape表示  矩陣是 多少x多少的

In:x2.shape
out: (3,5)


In:x1.size
out: 10       # size表示 矩陣中元素的個數

In:x2.size
out: 15

numpy.array 的資料訪問

In:x2
out:array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])


In:x2[0][0]
out:0     # [][] 的訪問方法  是可行的, 但不建議

In:x2[2,2]
out: 12   # 建議 [,]這樣訪問



# python切片的語法同樣適用於np.array
In:x1
out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In:x1[:4]
out: array([0, 1, 2, 3])



# 對於多維的訪問 必須使用[,] 不能使用[][]

In: x2[:2][:3]
out: array([[0, 1, 2, 3, 4],       # 得到的不是 前兩行的 前3列
       [5, 6, 7, 8, 9]])
       
In: x2[:2,:3]
out: array([[0, 1, 2],             # 得到了想要的結果
       [5, 6, 7]])



# 子矩陣的修改會 直接影響到父矩陣
# np.array中因為追求效率, 所以子矩陣是父矩陣的引用

In: subX = x2[:2,:3]
In: subX
out: array([[0, 1, 2],
       [5, 6, 7]])
       
In: subX[0,0] = 100000
In: subX
out: array([[100000,      1,      2],
       [     5,      6,      7]])


In: x2
out:array([[100000,      1,      2,      3,      4],
       [     5,      6,      7,      8,      9],
       [    10,     11,     12,     13,     14]])        # 可以看到父矩陣的[0,0]元素也改變了
       
# 同理, 父矩陣的元素改變, 子矩陣也會改變




# 如果想要子矩陣 與 父矩陣 不互相影響, 可以使用copy

In: subX = x2[:2, :3].copy()     # 這樣子矩陣和父矩陣就不會相互影響了

reshape

In: x1.reshape(2,5)
out: array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])


# 想把 x1 變為10行, 有多少列  不清楚, 可以用-1代替
In: x1.reshape(10, -1)
out:array([[0],
       [1],
       [2],
       [3],
       [4],
       [5],
       [6],
       [7],
       [8],
       [9]])
       
       
       
In: x1.reshape(2, -1)   # 變為2 行, 多少列 不去管
out:array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

五.Numpy陣列(和矩陣)的合併與分割

合併

# 一維矩陣的合併
In:x = np.array([1,2,3])
In:y = np.array([3,2,1])

In:np.concatenate([x,y])
out:array([1, 2, 3, 3, 2, 1])

In:z = np.array([666,666,666])
In:np.concatenate([x,y,z])
out: array([  1,   2,   3,   3,   2,   1, 666, 666, 666])



# 二維矩陣  的合併
In: A = np.array([[1,2,3],
In:             [4,5,6]])
In: np.concatenate([A,A])     # 這裡預設引數axis=0, 即拓展行數
out: array([[1, 2, 3],
       [4, 5, 6],
       [1, 2, 3],
       [4, 5, 6]])
       

In: np.concatenate([A,A], axis=1)   # 拓展列
out: array([[1, 2, 3, 1, 2, 3],
       [4, 5, 6, 4, 5, 6]])
       
       

# 不同維度矩陣的合併方法一
In: np.concatenate([A, z.reshape(1, -1)])   # 需要將z的維度 由3行1列 變為1行3列, 和A一樣
out: array([[  1,   2,   3],
       [  4,   5,   6],
       [666, 666, 666]])



# 補充說明
[1,2,3]  向量
[[1,2,3]]  1行3列矩陣
[[1],[2],[3]]  3行1列矩陣


# 不同維度矩陣的合併方法二: vstack和hstack
In:np.vstack([A,z])       # A的列數和z的元素個數相等, 所以使用vstack垂直方向合併, 並不需要對z進行reshape
out: array([[  1,   2,   3],
       [  4,   5,   6],
       [666, 666, 666]])
       
In:B = np.array([[777],[777]])     # [777,777]就表示向量, hstack會報錯
In:B
out:array([[777],
       [777]])

In: np.hstack([A,B])
out: array([[  1,   2,   3, 777],
       [  4,   5,   6, 777]])

分割

  • 一維的分割
In:x = np.arange(10)
In:x1, x2, x3 = np.split(x, [3, 7])

In:x1
out:array([0, 1, 2])

In:x2
out:array([3, 4, 5, 6])

In:x3
out:array([7, 8, 9])
  • 多維的分割
# 行方向的分割
In:A = np.arange(16).reshape((4,4))
In:A
out:array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
    
    
In:A1, A2 = np.split(A, [2])      # 或者  upper, lower = np.vsplit(A, [2])
In:A1
out:array([[0, 1, 2, 3],
       [4, 5, 6, 7]])

In:A2
out:array([[ 8,  9, 10, 11],
       [12, 13, 14, 15]])
       

# 列方向的分割
In:A1, A2 = np.split(A, [2], axis=1)    # axis=1指定列分割  或者 left,right = np.hsplit(A, [2])
In:A1
out:array([[ 0,  1],
       [ 4,  5],
       [ 8,  9],
       [12, 13]])
       
In:A2
out:array([[ 2,  3],
       [ 6,  7],
       [10, 11],
       [14, 15]])

六. Numpy中矩陣的運算

對矩陣的元素的元素

# python原生list 實現 將矩陣的元素都x2
n = 10
L = [i for i in range(n)]
A = [2*e for e in L]


# numpy.array實現   將矩陣的元素都x2
import numpy as np
L = np.arange(n)
A = np.array(2*e for e in L)  


# np.array  如果用%%time測試執行時間, 發現比python的list實現, 快得多
# np.array 可以直接*2, 符合矩陣的運算結果, python的list*2 則是list+list  連起來

A = L*2   # 可以直接得到每個元素*2的新矩陣


# np.array  幾乎支援其他所有運算  如  
L+1      每個元素+1
L-1
L*2
L/3
1/L      每個元素都變為  倒數
L//5      每個元素整除5
L**3      每個元素冪運算
L%7        每個元素求餘數

對矩陣間的運算

  • 運算子進行的是 矩陣元素間的運算
In:A=np.arange(4).reshape(2,2)
In:A
out:array([[0, 1],
       [2, 3]])
       
In:B=np.full((2,2), 10)
In:B
out:array([[10, 10],
       [10, 10]])
      
In:A+B
out:array([[10, 11],
       [12, 13]])

In:A-B
out:array([[-10,  -9],
       [ -8,  -7]])

In:A*B
out:array([[ 0, 10],
       [20, 30]])
       
In:A/B
out:array([[0. , 0.1],
       [0.2, 0.3]])
       

#  可以看到都是元素間 進行運算, 而不是矩陣的運算
  • 矩陣運算
# 矩陣相乘
In: A.dot(B)
out:array([[10, 10],
       [50, 50]])
       

# 矩陣的轉置
In: A.T
out: array([[0, 2],
       [1, 3]])

  • 向量和矩陣的運算
In:v=np.array([1,2])
In:A
out:array([[0, 1],
       [2, 3]])
       
In:v+A       # 向量直接與矩陣相加, 會讓矩陣的每一行都加上該向量
out:array([[1, 3],
       [3, 5]])
       
       

In: np.vstack([v]*A.shape[0])   # 或者可以把向量變為維度和A一樣的矩陣 再進行相加
out:array([[1, 2],
       [1, 2]])


In:np.tile(v, (2,1))        # tile也可以改變維度, 2表示複製為2行, 1表示複製為1列, 即列方向不拓展 
out:array([[1, 2],
       [1, 2]])



In: v*A     # 這樣的到 是 v與A的每一行乘, 不是矩陣的乘法
out:array([[0, 2],
       [2, 6]])


In: v.dot(A)     # 想要矩陣相乘   依然使用dot
out:array([4, 7])


In: A.dot(v)     # v是向量, numpy會自動把v變為2*1的矩陣
out:array([2, 8])
  • 矩陣的逆
In:A
out:array([[0, 1],
       [2, 3]])

In:invA = np.linalg.inv(A)   # 得到A的逆矩陣 invA
In:invA
out:array([[-1.5,  0.5],
       [ 1. ,  0. ]])


In: A.dot(invA)    # 原矩陣乘 逆矩陣  得到單位矩陣
out:array([[1., 0.],
       [0., 1.]])



七. Numpy的聚合運算

# 聚合

import numpy as np
L = np.random.random(100)     # 生成100個元素的隨機陣列
L.dtype
out:dtype('float64')


np.sum(L)   # 求和
out:48.17857390434729



sum(L)      # python的sum 也可以實現, 但 速度比np.sum  慢非常多
out:48.178573904347246


np.min(L)    # 找出最小值
out:0.007983418226231609

np.max(L)     # 找出最大值
out:0.9875521184825461


X= np.arange(16).reshape(4,-1)
X
out:array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])


np.sum(X)    # 預設為  對所有元素求和
out:120


np.sum(X, axis=0)    # 對每一列  求和,  axis=0可以理解為 壓縮為一行
out:array([24, 28, 32, 36])


np.sum(X, axis=1)    # 對每一行 求和,  axis=1可以理解為  壓縮為一列
out:array([ 6, 22, 38, 54])


np.prod(X)   # 所有元素的乘積
out:0


np.mean(X)   # 所有元素均值
out:7.5

np.median(X)   # 所有元素 中位數
out:7.5


np.percentile(X, q=50)    # 在50%的 地方找到 百分位點   和np.median(X) 等價
out:7.5

np.percentile(X, q=90)     # 在90% 的地方找到百分位點
out:13.5


np.var(X)   # 方差
out:21.25


np.std(X)    # 標準差
out:4.6097722286464435

八. Numpy中的索引運算(arg運算)

  • 找到最值的索引
x = np.random.normal(0,1,size=1000000)   # 生成 均值為0 方差為1 的正態分佈點
np.min(x)    # 得到了 最小值, 但想知道 該值 在哪個位置
out:-5.024177664592925


np.argmin(x)   # 找到最小值   的索引位置
out:628924

#同樣的 有argmax
  • 排序和使用索引
# 排序
x = np.arange(16)
x
out:array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])


np.random.shuffle(x)    # shuffle 將x中元素順序打亂
x    
out:array([ 3,  4,  0,  7, 11,  8, 12, 15,  5, 14, 13,  1,  9,  6, 10,  2])


np.sort(x)      # 得到一個新的 排好序的數列
out:array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])

x.sort()        # 在原來的x中排序
x  
out:array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])





# arg排序
np.random.shuffle(x)   # 打亂順序
x
out:array([13, 10,  7,  0, 12,  5, 14, 15,  9,  2,  3,  6, 11,  4,  8,  1])

np.argsort(x)     # 得到的是索引, 按索引 找到的元素, 都是排序好的元素
out:array([ 2, 11,  9, 15,  1, 10, 14,  7,  4,  3,  5,  6, 12,  8,  0, 13])





# partition操作
np.partition(x,3)    # 小於3的放3前面   大於3的放3後面,   和快速排序中的partition一致
out:array([ 1,  0,  2,  3,  4,  6,  7,  5,  8,  9, 10, 12, 11, 13, 14, 15])

np.argpartition(x,3)   # 同樣有 arg方法
out:array([15,  3,  9, 10, 13, 11,  2,  5, 14,  8,  1,  4, 12,  0,  6,  7])





# 多維的排序
X = np.random.randint(10, size=(4,4))    # 生成4x4的 隨機矩陣
X
out:array([[2, 1, 7, 8],
       [0, 8, 7, 3],
       [7, 6, 1, 9],
       [0, 2, 9, 8]])


np.sort(X)   # 預設axis=1
out:array([[1, 2, 7, 8],
       [0, 3, 7, 8],
       [1, 6, 7, 9],
       [0, 2, 8, 9]])


np.sort(X, axis=1)   # 沿著列的方向  對每一行排序
out:array([[1, 2, 7, 8],
       [0, 3, 7, 8],
       [1, 6, 7, 9],
       [0, 2, 8, 9]])


np.sort(X, axis=0)   # 沿著行的方向  對每一行列序
out:array([[0, 1, 1, 3],
       [0, 2, 7, 8],
       [2, 6, 7, 8],
       [7, 8, 9, 9]])

九. Numpy中的比較和Fancy indexing

  • Fancy indexing
import numpy as np

x = np.arange(16)
x
out:array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])



[x[3], x[5],x[8]]     # 得到新的陣列, 但numpy有更加方便的方法
out: [3, 5, 8]


ind = [3,5,8]     # numpy提供的方法, 即fancy indexing
x[ind]
out:array([3, 5, 8])



# 多維的Fancy indexing
X = x.reshape(4,-1)
X
out:array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
       
row = np.array([0,1,2])    #現在想要得到3個點, row中存放這3個點的所在行數
col = np.array([1,2,3])    # col 放3個點所在列數
X[row, col]
out:array([ 1,  6, 11])


X[0, col]
out:array([1, 2, 3])

X[:2, col]    # 前兩行的  對應col  得到數值
out:array([[1, 2, 3],
       [5, 6, 7]])


X[1:3,col]
out:array([[ 5,  6,  7],
       [ 9, 10, 11]])

  • numpy.array的比較
x
out:array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15])


x > 3
out:array([False, False, False, False,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True])

x < 3
out:array([ True,  True,  True, False, False, False, False, False, False,
       False, False, False, False, False, False, False])


x >= 3
out:array([False, False, False,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True])

x <= 3
out:array([ True,  True,  True,  True, False, False, False, False, False,
       False, False, False, False, False, False, False])



x == 3
out:array([False, False, False,  True, False, False, False, False, False,
       False, False, False, False, False, False, False])
       
       
       
# 更加複雜的
2*x == 24 - 4*x
out:array([False, False, False, False,  True, False, False, False, False,
       False, False, False, False, False, False, False])
       

# x中有多少元素 <=3
np.sum(x<=3)
out:4


# x中有多少元素 <=3  的另一種方法
np.count_nonzero(x<=3)
out:4


# x中是否存在0
np.any(x == 0)
out: True


# 值>10 且為 偶數的  元素個數
np.sum((x % 2==0) | (x>10))
out:11