數據分析之Numpy庫

1 Numpy簡介

Numpy(Numerical Python)是一個開源的高性能的科學計算和數據分析庫,用於快速處理任意維度的數組。並且,Numpy支持常見的數組和矩陣操作。Numpy使用ndarray對象來處理多爲數組,ndarray對象是一個快速靈活的大數據容器。

2 ndarray簡介

Python中有列表,可當數組使用。Python中也有array模塊,但是不支持多維數組。並且列表和array模塊都沒有科學運算函數。所以,Python不適合做矩陣等科學計算。Numpy沒有使用Python本身的數組機制,而是提供了ndarray這個n維數組類型對象,ndarray不僅能夠很方便地對數組進行存取,而且擁有豐富的科學計算函數,如向量的加法、減法、乘法等。下面通過實例演示創建一個ndarray多維數組:

# 導入numpy函數庫並指定庫的別名
import numpy as np
# 創建一維數組
array1 = np.array([1, 2, 3, 4])
# 創建二維數組
array2 = np.array([[1, 2, 3, 4],[5, 6, 7, 8]])
# 創建三維數組
array3 = np.array([[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]],[[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12]]])
array1:array([1, 2, 3, 4])
array2:array([[1, 2, 3, 4],
       [5, 6, 7, 8]])
array3:array([[[ 1,  2,  3,  4],
        [ 5,  6,  7,  8],
        [ 9, 10, 11, 12]],

       [[ 1,  2,  3,  4],
        [ 5,  6,  7,  8],
        [ 9, 10, 11, 12]]])
3 ndarray與list執行效率的對比

使用Python的list可以作爲一維數組,通過列表的嵌套可以實現多維數組。那爲什麼還要使用Numpy的ndarray,其實使用ndarray處理數組,其效率要比list要高很多,下面通過例子來比較下兩者的執行效率:

import random
import numpy as np
# 定義一個空列表用於存放(數組)元素
lst = []
# 向lst中添加一千萬個元素
for i in range(10000000):
    lst.append(random.random())
%time sum01 = sum(lst) # 使用Python中的sum函數對數組元素進行求和;%time是魔法方法,可以查看當前行代碼運行一次需要花費的時間。
lst2 = np.array(lst) # 將lst的存儲方式轉換成ndarray中的存儲方式
%time sum02 = np.sum(lst2) # 使用ndarray中的sum對同樣的數組進行求和
第一次運行上面的代碼:
CPU times: user 40.8 ms, sys: 70 µs, total: 40.8 ms
Wall time: 40.9 ms
CPU times: user 4.07 ms, sys: 0 ns, total: 4.07 ms
Wall time: 3.87 ms

第一次運行上面的代碼:
CPU times: user 41.1 ms, sys: 0 ns, total: 41.1 ms
Wall time: 41.1 ms
CPU times: user 3.86 ms, sys: 0 ns, total: 3.86 ms
Wall time: 3.87 ms

第三次運行上面的代碼:
CPU times: user 40.8 ms, sys: 87 µs, total: 40.9 ms
Wall time: 40.9 ms
CPU times: user 4.23 ms, sys: 31 µs, total: 4.26 ms
Wall time: 4.07 ms

很明顯使用numpy的ndarray對數組求和的效率要比原生Python的sum函數求和高10倍以上。機器學習最大的特點是需要對大量的數據做運算,如果沒有一個快速的解決方案,那麼可能Python在機器學習領域就達不到很好的效果。Numpy專門對ndarray的操作和運算進行設計,所以,數組的存儲效率和輸入輸出性能遠優於Python中的嵌套列表。數組越大,Numpy的優勢就越明顯。

4 ndarray的優勢
  • 內存塊風格:ndarray在存儲數據的時候是直接存儲,Python的list中的數據不是直接存儲,需要先找尋一個地址,然後通過地址找到需要的內容。ndarray中的所有元素的類型都是相同的,所以ndarray在存儲元素時,內存是可以連續的。而Python中list中的元素是任意的,所以只能通過尋址的方式找到下一個元素。ndarray在通用性上要輸於list,但在科學計算中,Numpy的ndarray就可以省掉很多循環語句,代碼使用方面比Python的list要簡潔。
  • ndarray支持並行化運算(向量化運算):Numpy內置並行運算功能,當系統有多個核心時,做運算會自動做並行運算。
  • 效率遠高於純Python代碼,Numpy底層使用C語言編寫,內部解除GIL(全局解釋器鎖),其對數組的操作速度不受Python GIL的影響。
5 ndarray數組的屬性

數組的維度:

# 導入numpy模塊併爲模塊設置別名
import numpy as np
# 創建一個維度是3行4列的ndarray數組
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.shape
Out[](3, 4)

數組的維數:

# 導入numpy模塊併爲模塊設置別名
import numpy as np
# 創建一個維度是3行4列的ndarray數組
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.ndim
Out[]2

數組中的元素數量:

# 導入numpy模塊併爲模塊設置別名
import numpy as np
# 創建一個維度是3行4列的ndarray數組
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.size
Out[]12

一個數組元素的長度(字節):

# 導入numpy模塊併爲模塊設置別名
import numpy as np
# 創建一個維度是3行4列的ndarray數組
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.itemsize
Out[]8

數組元素的類型:

# 導入numpy模塊併爲模塊設置別名
import numpy as np
# 創建一個維度是3行4列的ndarray數組
array01 = np.array([
    [80, 78, 98, 88],
    [89, 87, 89, 78],
    [78, 84, 89, 87]
])
array01.dtype
Out[]:dtype('int64')
6 ndarray數組的形狀

一維數組:

import numpy as np
a = np.array([1, 2, 3, 4, 5])
print(a)
print(a.shape)
[1 2 3 4 5]
(5,) # 表示一維數組,5:數組中有5個元素

二維數組:

import numpy as np
b = np.array([
    [1, 2, 3, 4, 5],
    [4, 5, 6, 7, 8]
])
print(b)
print(b.shape)
[[1 2 3 4 5]
 [4 5 6 7 8]]
(2, 5) # 有兩個元素,表示的是二維數組。2:二維數組中有兩個一維數組;5:一維數組中有5個元素

三維數組(三維數組是二維數組的疊加):

import numpy as np
c = np.array([
    [[1, 2, 3, 4, 5],
    [4, 5, 6, 7, 8]],
    [[9, 10, 11, 12, 13],
    [14, 15, 16, 17, 18]]
])
print(c)
print(c.shape)
[[[ 1  2  3  4  5]
  [ 4  5  6  7  8]]
 [[ 9 10 11 12 13]
  [14 15 16 17 18]]]
(2, 2, 5) # 第一個2:有2個二維數組;第二個2:二維數組中有2個一維數組;3:在一維數組中有3個元素
7 ndarray數組的類型

不指定數組類型(整型):

import numpy as np
a = np.array([
    [[1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,17]],
    [[1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,12]]
])
a.dtype
dtype('int64')

不指定數組類型(小數):

import numpy as np
a = np.array([
    [[1.1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,17]],
    [[1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,12]]
])
a.dtype
dtype('float64')

如果不指定,整型默認是int64,小數默認是float64。如果指定數組類型:

指定數組類型,將整型指定爲float64類型:

import numpy as np
a = np.array([
    [[1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,17]],
    [[1, 2, 3, 4, 5, 6],
    [7, 8, 9, 10, 11,12],
    [12, 13, 14, 15, 16,12]]
], dtype=np.float64)
print(a)
a.dtype
[[[ 1.  2.  3.  4.  5.  6.]
  [ 7.  8.  9. 10. 11. 12.]
  [12. 13. 14. 15. 16. 17.]]

 [[ 1.  2.  3.  4.  5.  6.]
  [ 7.  8.  9. 10. 11. 12.]
  [12. 13. 14. 15. 16. 12.]]]
dtype('float64')

不指定數組類型(字符串):

import numpy as np
a = np.array(['I', 'Like' ,'qianqian'])
a
array(['I', 'Like', 'qianqian'], dtype='<U8')

指定數組類型(字符串):

import numpy as np
a = np.array(['I', 'Like' ,'qianqian'], dtype=np.string_)
a
array([b'I', b'Like', b'qianqian'], dtype='|S8') # S:String;8:數組中最長字符串是8個字母
8 ndarray數組的生成

從已存在的數組中生成數組的兩種方法,numpy.arraynumpy.asarray方法,下面通過一個小案例來區別這兩種方法:

首先創建一個數組作爲已存在數組:

import numpy as np
a = np.array([[1, 2, 3, 4, 5, 6],[7,8,9,10,11,112]])
a
array([[  1,   2,   3,   4,   5,   6],
       [  7,   8,   9,  10,  11, 112]])

使用array在原有數組的基礎上生成數組(深度拷貝):

a1 = np.array(a) # 深拷貝
a1[0, 0] = 0
a
array([[  1,   2,   3,   4,   5,   6],
       [  7,   8,   9,  10,  11, 112]])

使用asarray在原有數組的基礎上生成數組:(淺拷貝)

a2 = np.asanyarray(a) # 淺拷貝
a2[0, 0] = 0
a
array([[  0,   2,   3,   4,   5,   6],
       [  7,   8,   9,  10,  11, 112]])

生成固定範圍的數組:

創建等差數列的數組,指定數量,使用的函數是:linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,axis=0)

import numpy as np
arr = np.linspace(0,21,6) # start:0,序列的起始值; stop:20,序列的終止值; num:5, 要生成的等間隔樣例數量, 默認是50。endpoint:序列中是否是否包含stop值,默認是True
arr
array([ 0. ,  4.2,  8.4, 12.6, 16.8, 21. ])

創建等差數列的數組,指定步長,使用的函數:arange(start=None, *args, **kwargs)

import numpy as np
arr = np.arange(0, 20, 2, dtype=np.int64) # step:2,步長;dtype:數據類型
arr
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

創建等比數列,使用的函數:logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None,axis=0)

import numpy as np
# 注意這裏是生成10的多少次方
arr = np.logspace(0, 2, 3) # num是要生成等比數列的數量;0、2的意思分別是10的0次方~10的2次方;3:生成3個數
arr
array([  1.,  10., 100.])

創建隨機數組(正太分佈方式),使用np.random模塊創建正太分佈有三種方式,分別是:randn(*dn),normal(loc=0.0, scale=1.0, size=None),standard_normal(size=None)。

  • randn:從標準動態分佈中返回一個或多個樣本值。
  • normal:返回指定形狀的標準正太分佈數組。loc:此動態分佈的均值(對應着整個分佈的中心);scale:概率分佈的標準差,值越大越矮胖,反之越瘦高。size:輸出的是shape,默認是None,只輸出一個值。
  • standard_normal:返回指定形狀的標準正太分佈的數組

生成均值爲1.75,標準差爲1的100000000個正態分佈數據。使用到的函數:normal(loc=0.0, scale=1.0, size=None)

# 導入相關模塊
import numpy as np
import matplotlib.pyplot as plt
# 數據的準備
x = np.random.normal(1.75, 1, 100000000) # array是一維數組,也就是一個列表
# 創建畫布
plt.figure(figsize=(8,4), dpi=100)
# 繪製圖像(繪製直方圖)
plt.hist(x, 1000) # 1000:1000組數據
# 顯示圖像
plt.show()

在這裏插入圖片描述
模擬生成一組股票的漲跌幅數據:隨機生成4支股票1周的交易日漲幅數據(隨機生成漲跌幅在某個正太分佈內,如均值是0,方差是1):

import numpy as np
arr = np.random.normal(0, 1, (4,5))
arr
array([[ 1.39648189,  0.17949331, -0.0393186 ,  1.54571909, -0.89729191],
       [-1.30231063, -0.21940802,  0.43169118, -0.68724142, -1.11523206],
       [-1.93539031, -2.21212029, -1.39101401, -2.27047266, -0.1254774 ],
       [ 1.67693295, -2.22111556,  1.5863305 ,  0.69848128,  2.25766984]])

創建隨機數組(均勻分佈方式),使用np.random模塊創建正太分佈有三種方式,分別是:rand(*dn),uniform(low=0.0, high=1.0, size=None),randint(low, high=None, size=None, dtype=‘l’)

  • rand:返回[0.0,1.0)內的一組均勻分佈的數。
  • uniform:從一個均勻分佈[low=0.0, hegh=1.0, size=None)中隨機採樣,low是採用下界,float類型,默認是0;high是採樣下界,float類型,默認值是1。size是輸出樣本的數目,int或元祖類型。如size=(m,n,k)則輸出mnk個樣本,缺省時輸出1個值。返回值:ndarray類型,其形狀和參數size中的描述一致。
  • randint:從一個均勻分佈中隨機採樣,生成一個整數或N維整數數組。對於取數範圍,如果high不是None時,取[low,high)之間的隨機數,否則取值[low,high)之間隨機整數。
# 導入模塊
import numpy as np
# 準別數據,生成均勻分佈的數據
x = np.random.uniform(-1, 1, 100000000)
# 創建畫布
plt.figure(figsize=(8,4), dpi=100)
# 繪製圖像(繪製直方圖)
plt.hist(x, 1000) # 1000:1000組數據
# 顯示圖像
plt.show()

在這裏插入圖片描述

9 ndarray數組的索引和切片
  • 一維數組的索引和切片
import numpy as np
arr = np.array([1, 2, 3, 4])
print(arr)
arr[0]
[1 2 3 4]
1
  • 二維數組的索引和切片
import numpy as np
arr2 = np.array([[1, 2, 3, 4],[5, 6, 7, 8]])
print(arr2)
arr2[1,1]
[[1 2 3 4]
 [5 6 7 8]]
6
  • 三維數組的索引和切片
import numpy as np
arr3 = np.array([[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], [[13, 14, 15, 16], [17, 18, 19, 20], [21, 21, 22, 23]]])
print(arr3)
arr3[1, 1, 1]
[[[ 1  2  3  4]
  [ 5  6  7  8]
  [ 9 10 11 12]]

 [[13 14 15 16]
  [17 18 19 20]
  [21 21 22 23]]]
18
10 ndarray數組形狀的修改
  • reshape(self, shape, order='C ')函數的應用
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
# 打印這個數組的形狀
print(arr.shape)
# 修改數組的形狀
arr2 = arr.reshape([6, 3])
# 打印改變後數組的形狀
print(arr2.shape)
arr2
(3, 6)
(6, 3)
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12],
       [13, 14, 15],
       [16, 17, 18]])

當不知到有多少列的時候:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
# 打印這個數組的形狀
print(arr.shape)
# 修改數組的形狀
arr2 = arr.reshape([6, -1])
# 打印這個數組的形狀
print(arr2.shape)
arr2
(3, 6)
(6, 3)
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12],
       [13, 14, 15],
       [16, 17, 18]])

當不知道有多少行的時候:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
# 打印這個數組的形狀
print(arr.shape)
# 修改數組的形狀
arr2 = arr.reshape([-1, 2])
# 打印這個數組的形狀
print(arr2.shape)
arr2
(3, 6)
(9, 2)
array([[ 1,  2],
       [ 3,  4],
       [ 5,  6],
       [ 7,  8],
       [ 9, 10],
       [11, 12],
       [13, 14],
       [15, 16],
       [17, 18]])
  • resize(self, new_shape, refcheck=True)函數的應用,要區別與reshape方法,其返回結果並不是新的數組,而是把原來的數組給修改了
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
# 打印這個數組的形狀
print(arr.shape)
# 修改數組的形狀
arr.resize([2,8])
# 打印這個數組的形狀
print(arr.shape)
arr
(3, 6)
(2, 8)
array([[ 1,  2,  3,  4,  5,  6,  7,  8],
       [ 9, 10, 11, 12, 13, 14, 15, 16]])
  • 數組的轉置,將數組的行列進行互換,使用數組名.T
# 數組的轉置
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
arr.T
array([[ 1,  7, 13],
       [ 2,  8, 14],
       [ 3,  9, 15],
       [ 4, 10, 16],
       [ 5, 11, 17],
       [ 6, 12, 18]])
11 ndarray數組類型的修改
  • ndarray.astype(type):返回修改類型之後的數組
# 返回修改了類型之後的數組
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
print(arr.dtype)
arr2 = arr.astype(np.float)
arr2
int64
array([[ 1.,  2.,  3.,  4.,  5.,  6.],
       [ 7.,  8.,  9., 10., 11., 12.],
       [13., 14., 15., 16., 17., 18.]])
  • ndarray.tostring([order])或者ndarray.tobytes([order]):構造包含數組原始數據字節的Python字節
# 構造包含數組原始數據字節的Python字節1
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
str_arr = arr.tostring()
str_arr
b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00'
# 構造包含數組原始數據字節的Python字節2
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [13, 14, 15, 16, 17, 18]])
str_arr = arr.tobytes()
str_arr
b'\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x00'
12 ndarray數組的去重

數組去重的方法是unique(ar, return_index=False, return_inverse=False,return_counts=False, axis=None):

# 返回修改了類型之後的數組
import numpy as np
arr = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 2, 10, 5, 6], [13, 14, 15, 16, 17, 18]])
arr2 = np.unique(arr)
arr2
array([ 1,  2,  3,  4,  5,  6,  7,  8, 10, 13, 14, 15, 16, 17, 18])
13 ndarray的運算
  • 邏輯運算
# 生成10名同學5門課程的分數
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
# 取出最後4名同學的成績,用於邏輯判斷
ret1 = scores[6:, 0:5] # 或者scores[6:, 0:5] 
# 邏輯判斷,如果成績不小於60分,標記爲True,否則爲False
ret2 = ret1 > 60 # 返回的結果是標記後的
'''
array([[False,  True,  True,  True,  True],
       [ True,  True,  True,  True, False],
       [ True,  True, False,  True,  True],
       [ True,  True, False,  True,  True]])
'''
ret1[ret1 > 60] = 1
ret1
'''
array([[54, 51, 59,  1,  1],
       [ 1,  1,  1,  1,  1],
       [ 1,  1, 60,  1,  1],
       [57,  1,  1,  1,  1]])
'''
  • 通用判斷函數

numpy.all方法:

'''
numpy.all方法是:只要有一個不滿足條件,就返回False;所有都滿足條件,返回True
判斷前兩名同學的成績是否都及格
'''
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores[0:2, :])
ret = np.all(scores[0:2, :] > 90)
ret
[[77 81 89 51 66]
 [78 64 53 53 70]]
False

numpy.any方法:

'''
numpy.any方法是:只要有一個滿足條件,就返回True;所有都不滿足條件返回False
判斷前兩名同學的成績是否有不小於90分的
'''
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores[0:2, :])
ret = np.any(scores[0:2, :] > 90)
ret
[[82 97 82 79 53]
 [54 81 91 67 64]]
True
  • 三元運算符

通過使用numpy.where能夠進行更加複雜的運算:

# 將前四名學生的前四門課程中成績中大於60的置爲1,否則置爲0
import numpy as np
scores = np.random.randint(50, 100, (10, 5))[:4, :4]
print(scores)
np.where(scores > 60, 1, 0)
[[76 84 84 52]
 [52 85 50 90]
 [57 71 93 92]
 [90 72 66 67]]
array([[1, 1, 1, 0],
       [0, 1, 0, 1],
       [0, 1, 1, 1],
       [1, 1, 1, 1]])

複合邏輯需要結合np.logical_and和np.logical_or使用:

# 將前四名學生前四門課程中成績大於60且小於90的置爲1,否知置爲0
import numpy as np
scores = np.random.randint(50, 100, (10, 5))[:4, :4]
print(scores)
np.where(np.logical_and(scores > 60, scores < 90), 1, 0)
[[61 99 91 92]
 [78 80 78 56]
 [63 88 80 59]
 [84 79 65 86]]
array([[1, 0, 0, 0],
       [1, 1, 1, 0],
       [1, 1, 1, 0],
       [1, 1, 1, 1]])
# 將前四名學生前四門課程中成績大於90或小於60的置爲1,否知置爲0
import numpy as np
scores = np.random.randint(50, 100, (10, 5))[:4, :4]
print(scores)
np.where(np.logical_or(scores > 90, scores < 60), 1, 0)
[[76 63 99 78]
 [84 85 74 56]
 [72 72 92 61]
 [56 54 89 60]]
array([[0, 0, 1, 0],
       [0, 0, 0, 1],
       [0, 0, 1, 0],
       [1, 1, 0, 0]])
14 ndrray統計運算相關的函數

max(a, axis)函數的使用:

# 取最大值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.max(scores)
[[82 51 86 57 79]
 [90 87 50 97 90]
 [81 93 72 69 90]
 [86 50 83 65 83]
 [68 66 78 59 65]
 [71 64 56 50 72]
 [79 69 91 97 76]
 [68 67 64 83 54]
 [66 63 60 58 53]
 [87 64 63 55 60]]
97

min(a, axis)函數的使用:

# 取最小值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.min(scores)
[[83 81 55 73 93]
 [57 61 51 60 91]
 [66 77 83 95 56]
 [75 76 58 59 96]
 [90 72 72 53 84]
 [83 67 93 82 57]
 [50 91 51 98 62]
 [83 53 91 78 91]
 [99 77 93 81 99]
 [89 71 73 81 87]]
50

mean(a, axis, dtype)函數的使用:

# 取平均值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.mean(scores)
[[50 90 77 76 78]
 [92 84 76 59 58]
 [77 69 66 73 68]
 [69 57 64 94 75]
 [82 52 97 93 57]
 [73 53 88 64 60]
 [84 98 64 65 88]
 [72 54 67 61 57]
 [99 83 73 80 64]
 [70 63 65 94 58]]
72.6

也可以按照行和列求解最大值、最小值、平均值等,下面以求解最大值、最小值爲例子:

# 按照列求最大值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.max(scores, axis=0)  # axis=0表示按照列來求解
[[57 66 72 90 69]
 [85 90 98 95 71]
 [97 75 83 57 55]
 [81 77 95 92 61]
 [79 68 79 54 66]
 [50 52 95 52 96]
 [55 64 86 54 73]
 [63 67 78 56 84]
 [54 76 92 88 89]
 [52 79 75 91 62]]
array([97, 90, 98, 95, 96])
# 按照行求最大值
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.max(scores, axis=1)  # axis=1表示按照行來求解
[[54 77 71 85 54]
 [65 89 95 69 75]
 [56 95 54 75 63]
 [62 84 58 94 89]
 [66 51 55 91 85]
 [70 97 75 70 84]
 [94 80 83 59 90]
 [76 70 55 99 74]
 [79 60 81 99 57]
 [96 82 50 57 80]]
array([85, 95, 95, 94, 91, 97, 94, 99, 99, 96])

argmax(a, axis)方法的使用:

# 最大值的下標
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.argmax(scores)
[[67 73 95 94 92]
 [52 91 74 96 76]
 [82 70 61 86 81]
 [90 69 57 86 66]
 [50 53 85 69 65]
 [84 69 81 61 52]
 [69 61 65 91 70]
 [87 50 68 78 83]
 [72 93 62 79 89]
 [99 75 77 53 87]]
45
# 按列求最大值的下標
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.argmax(scores, axis=0)
[[85 68 60 71 62]
 [65 71 86 60 84]
 [57 81 76 58 95]
 [57 83 66 73 55]
 [88 77 54 81 68]
 [78 53 54 99 54]
 [99 86 63 56 97]
 [92 96 52 83 57]
 [85 83 65 55 76]
 [79 77 67 63 69]]
array([6, 7, 1, 5, 6])
# 按行求最大值的下標
import numpy as np
scores = np.random.randint(50, 100, (10, 5))
print(scores)
np.argmax(scores, axis=1)
[[78 53 79 82 60]
 [61 92 72 56 61]
 [71 64 80 81 81]
 [95 55 81 85 74]
 [63 82 65 89 91]
 [94 62 52 61 93]
 [91 69 98 54 63]
 [76 53 93 86 83]
 [97 98 92 52 95]
 [70 60 75 83 74]]
array([3, 1, 3, 0, 4, 0, 2, 2, 1, 3])

argmin(a, axis)的使用同argmax(a, axis)的相似,統計運算中還可以求中位數[median(a, axis)]、平均值、標準差[std(a, axis, dtype)]和方差[var(a, axis, dtype)]等。

15 數組間的運算

數組與數之間的運算:

執行程序1:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
arr + 3 # 所有元素加3

打印結果:

array([[ 4,  5,  6,  7,  8],
       [ 9, 10, 11, 12, 13]])

執行程序2:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
arr / 2 # 所有元素除以2

打印結果:

array([[0.5, 1. , 1.5, 2. , 2.5],
       [3. , 3.5, 4. , 4.5, 5. ]])

執行程序3:

import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
arr * 3 # 所有元素乘3

打印結果:

array([[ 3,  6,  9, 12, 15],
       [18, 21, 24, 27, 30]])

注意:如果是列表*3,則只會分別粘貼複製3次列表中的元素,組成新的列表

數組與數組的運算:(不同形狀的數組是不可以在一起運算的)

測試程序:

import numpy as np
arr1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
arr2 = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
arr1 + arr2

測試結果:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-44-18acd144a7ff> in <module>
      2 arr1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
      3 arr2 = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
----> 4 arr1 + arr2

ValueError: operands could not be broadcast together with shapes (2,4) (2,5) 

廣播機制:數組在進行矢量運算時,要求數組的形狀是相等的。當形狀不相等的數組執行算術運算時,就會出現廣播機制,該機制會對數組進行擴展,使數組的形狀屬性值一樣。這樣,就可以進行矢量化運算。廣播機制實現了兩個或兩個以上數組的運算,即使這些數組的shape不是完全相同的,只要滿足一個條件即可:

  • 數組的某一維度等長
  • 其中一個數組的某一個維度是1

執行程序:

import numpy as np
arr1 = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]])
arr2 = np.array([[1], [2]])
print('arr1的形狀是:',arr1.shape)
print('arr2的形狀是:',arr2.shape)
arr1 + arr2

執行結果:

arr1的形狀是: (2, 6)
arr2的形狀是: (2, 1)
array([[ 2,  3,  4,  5,  6,  7],
       [ 9, 10, 11, 12, 13, 14]])

廣播機制需要擴展維度小的數組,使得它與維度大的數組的shape值相同,以便使用元素級函數或者運算符進行運算。

16 矩陣與向量相關

矩陣和數組的區別是矩陣必須是二維的,而數組可以是多維的。矩陣和向量的區別是向量是特殊的矩陣。
矩陣的加法:行和列相等可以進行加法,對應元素進行加和。
標量乘法:矩陣中的每個元素都要一一和標量進行相乘。
矩陣和向量乘法:m * n階的矩陣和n * 1階的向量進行相乘,得到m * 1階的向量
矩陣乘法:m * n矩陣乘以n * o,得到m*n階矩陣
矩陣乘法的性質:

  • 矩陣乘法不滿足交換律:AxB不等於BxA
  • 矩陣乘法滿足結合律:(AxB)xC=Ax(BxC)
  • 單位矩陣:主對角線上的元素都是1,其它元素都是0,這種矩陣是單位矩陣

矩陣的逆:如矩陣是一個m*m矩陣(方陣),如果有逆矩陣,則AA-1=A-1A。低階矩陣球逆的方法是待定係數法和初等變換
矩陣的轉置:矩陣的行轉置後變成矩陣的列,矩陣的列變成矩陣的行。
矩陣的運算:矩陣的運算可以使用在大學求最終成績上,很多位學生(決定矩陣的行數)的平時成績和期末成績組成n行2列的矩陣,再乘以0.7和0.3組成的2行1列的矩陣,得到n行1列的矩陣就是每位學生的最終成績。在numpy庫中矩陣乘法使用到matmul和dot函數:兩者相同點是都可以做矩陣之間的乘法,不同點是matmul不支持矩陣與標量的乘法,而dot支持

測試兩者都可以做矩陣之間的乘法

# 測試dot和matmul函數都可以做矩陣之間的乘法
import numpy as np
a = np.array([[89, 90], [88, 89], [87, 78]])
b = np.array([0.7, 0.3])
arr1 = np.matmul(a, b)
print(arr1)
arr2 = np.dot(a, b)
print(arr2)

測試結果:

[89.3 88.3 84.3]
[89.3 88.3 84.3]

測試只有dot函數支持矩陣與標量的乘法:

# 測試只有dot函數支持矩陣與標量的乘法
import numpy as np
a = np.array([[89, 90], [88, 89], [87, 78]])
arr1= np.dot(2,a)
print(arr1)
arr2= np.matmul(2, a)
[[178 180]
 [176 178]
 [174 156]]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-59-653e8ec1b561> in <module>
      4 arr1= np.dot(2,a)
      5 print(arr1)
----> 6 arr2= np.matmul(2, a)

ValueError: matmul: Input operand 0 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章