NumPy數組基礎


數組與向量化計算。優點:數組類型;快速的向量化計算(由於由C語言實現)
導入:

import numpy as np  # 標準的NumPy導入方式

比較NumPy的數組與list的效率,因爲NumPy用C語言實現。並且矩陣運算不需要循環。

# 100萬個數循環10次*2,計時
arr = np.arange(1000000)
ls = list(range(1000000))
%time for _ in range(10):arr2 = arr*2             # Wall time: 22.9 ms
%time for _ in range(10):ls2 = [x*2 for x in ls]  # Wall time: 750 ms

數據結構-ndarray:多維數組對象

數組內數據同類型,默認float型
屬性:
.shape: 各維度大小
.dtype: 數據類型
.ndim: 幾維

data = np.random.randn(2,3)  # 生成2*3的二維隨機數組
data
# array([[-0.00513612, -0.13435869,  0.41686502],
#        [-0.09536552, -0.65670825,  1.03684946]])
?np.random.randn(d0, d1, ..., dn) # 返回服從標準正態分佈的樣本
# 參數是各維度大小,參數爲空時返回一個符合的實數
  1. 生成一維數組:從任意序列使用np.array(seq) 轉換爲一維數組
l = [1,2,3]
arr = np.array(l)   # 列表轉換爲數組
arr.ndim  # 1
arr.dtype  # int32

或使用arange():range()的數組版,將range結果變成數組

np.arange(5)  # array([0, 1, 2, 3, 4])
np.arange(2,8,2)  # 從2到7,步長是2,array([2, 4, 6])
  1. 生成多維數組,從嵌套序列轉換,幾重嵌套就是幾維
l = [[1,2,3],[4,5,6]]
arr = np.array(l)
arr.shape            # (2, 3)

np.array(seq): 默認複製所有的數據
np.asarray(seq): 也是將序列轉換爲數組,但如果輸入已經是ndarray,則不再複製
3. 生成特殊數組

np.zeros(5)        # 生成全0數組,1*5,默認float型,array([0., 0., 0., 0., 0.])
np.ones((2,3))     # 生成全1數組,2*3,參數用元組給出
np.empty((2,3,2))  # 生成未初始化值的數組,不一定是0,可能是內存原來的垃圾值
np.identity(3)     # 生成3*3的對角矩陣,對角線全是1,等價於
np.eye(3)
其餘生成函數 描述(_like:就是與給定數組形狀一樣)
ones_like 根據所給數組生成形狀一樣的全1數組
zeros_like 同上,全0
empty_like 同上,全未初始化
full 根據給定形狀和數據類型生成指定數值的數組
full_like 根據給定數組生成形狀一樣但是內容是指定數值的數組

數據類型dtype

全名:np.類型名+元素位數:np.int8/16/32/64,np.float16/32/64/128,np.complex64/128/256,np.bool,np.string_,np.unicode
簡名:int,float,complex,bool(非0都是True),str
用場:

  1. 轉換爲數組時或生成數組時同時指定類型,通過參數dtype=
    np.array(seq,dtype=)
    np.empty(n,dtype=)
  2. 顯式改變類型:reresult = .astype(類型名) 總是返回一個新數組
    前提:類型之間要能轉換,浮點數轉爲整數則丟失小數部分
    arr2 = arr.astype(float) 等價於 arr2 = arr.astype(np.float64)

數組算術-向量化

等尺寸數組之間的算術操作是逐元素操作。
*:逐元素相乘
/:逐元素相除
**n:逐元素計算n次冪
<等大小比較:逐元素比較大小,返回同等大小的True/False數組
不同尺寸的數組間操作,將用到廣播特性。

索引與切片

1.一維數組直接索引與切片,同列表一樣。
注意,對切片賦值時,是賦給切片內所有的數據。

arr = np.arange(5)
arr[2:5] = 10
arr   # [ 0,  1, 10, 10, 10]

注意2:數組的切片類似於原數組的引用(指針),任何對切片的操作都將反映到原數組上。原因是NumPy設計爲處理非常大的數組,不能動不動就複製數組。如果一定要複製數組切片,則必須顯式的複製,如arr[5:8].copy()

arr = np.arange(5)
slice = arr[2:5]
print(slice)    # [2 3 4]
slice[:] = 10   # 引用數組的所有值
print(slice)    # [10 10 10]
print(arr)      # [ 0,  1, 10, 10, 10]

2.高維數組的一個索引是低一維的數組
索引單個元素:可以每個中括號一個索引也可以通過索引值的列表
比如二維數組 arr[0][2] 等價於 arr[0,2],軸0是行,軸1是列。
數組子集選擇中,返回的數組都是引用。
3. 數組切片
一維直接切
高維中,只有一組切片時是沿軸0切片,比如二維數組arr[:2]:選擇前兩行
多組切片也是逗號列表,比如arr[:2,1:]表示前兩行第2列到最後一列。
多組切片維度不變,但索引與切片混合時,得到維度減少的結果。

arr = np.eye(3)
arr[1:2,:2]    # array([[0., 1.]]),.ndim=2  ,兩組切片
arr[1,:2]      # array([0., 1.]),.ndim=1  ,索引與切片混合

對切片表達式賦值時,整個切片所有數據都被賦值

arr = np.eye(3)
arr[:,1:] = (6,3)   # 所有行,  # arr[:,1:] = 6,則後兩列全爲6
print(arr)

在這裏插入圖片描述

  • 布爾索引:使用邏輯表達式作爲索引
    比如data[(data<0) & (data>-3)] = 0
    與或非必須使用邏輯運算符&,|,!(~條件),不能使用and,or
  • 神奇索引:使用整數數組進行索引,見《數據分析》P103

數組轉置與換軸

.T屬性返回轉置後的數組
.reshape(各維度大小的元組,order=‘C’):改變數組形狀,默認按行排列,‘F’按列排列

arr = np.arange(6).reshape((2,3))  # 變成2*3
print(arr)
print(arr.T)   # .T屬性轉置

在這裏插入圖片描述
計算矩陣內積,即矩陣乘法

arr = np.random.randn(3,2)
print(arr)
np.dot(arr.T,arr)  # 3*2 2*3 = 2*2

在這裏插入圖片描述
轉置是換軸的一個特例,軸0(行)與軸1(列)互換,因爲二維數組換軸就是轉置。換軸只針對高維數組而言,
法一:a.swapaxes(axis1, axis2) : Return a view of the array with axis1 and axis2 interchanged.返回的是數據的視圖,沒有複製數據
法二:a.transpose(新的所有軸編號的元組)

# 換軸,對於3維數組,軸0是最外層,軸1是行,軸2是列
arr = np.arange(6).reshape((1,3,2),order='C') 
print(arr)
print(arr.swapaxes(1,2))  # 軸1與軸2互換,等價於下面
print(arr.transpose((0,2,1)))

在這裏插入圖片描述

通用函數ufunc

逐元素數組函數

arr = np.arange(5)
print(np.sqrt(arr))   # 根號
print(np.exp(arr))    # 指數

x = np.random.randn(3)
y = np.random.randn(3)
print('x:',x,'\ny:',y)
print('max:',np.maximum(x,y))   # 計算每個位置的元素最大值
decimals,integer = np.modf(x)  # 返回每個元素的小數部分和整數部分,各爲一個數組
print('小數:',decimals,'整數:',integer)

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
示例:根據網格數據計算x2+y2\sqrt{x^2+y^2}

points = np.arange(-5,5,0.01) # 1000個相同步長的點
xs, ys = np.meshgrid(points,points)  # 接受兩個一維數組,根據兩個數組的所有(x,y)對生成一個二維矩陣
print('xs:',xs)
z = np.sqrt(xs ** 2 + ys ** 2)
print('z:',z)

# 二維數組可視化
import matplotlib.pyplot as plt
plt.imshow(z,cmap='summer');plt.colorbar()  # 在圖旁邊把colorbar顯示出來
plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")  # 添加標題,公式用LaTeX表示

在這裏插入圖片描述
注:matplotlib.pyplot.imshow(X, cmap=None)
X: 要繪製的圖像或數組。
cmap: 顏色圖譜(colormap), 默認繪製爲RGB(A)顏色空間。例如;matplotlib.pyplot.imshow(img, cmap=‘jet’)

顏色圖譜的取值:

數組中的條件判斷np.where

典型用場:根據一個數組,根據條件改變裏面的值,變成另一個數組
np.where(condition, x, y): Return elements chosen from x or y depending on condition.
返回值 : An array with elements from x where condition is True, and elements from y elsewhere.

# 將矩陣中的正值替換爲2,負值不替換
arr = np.random.randn(4,4)
np.where(arr > 0,2,arr)  # 應該是逐元素判斷條件並應用

在這裏插入圖片描述

統計函數

axis問題:二維數據擁有兩個軸:軸0看做行,軸1看做列。
但軸向不等於軸,0軸向:沿着行的方向即垂直往下,1軸向:沿着列的方向即水平延伸。
在這裏插入圖片描述
統計函數裏的參數axis表示沿軸向計算(along)

arr = np.random.randn(2,3)
print(arr)
print(arr.mean(axis=1))  # 跨列計算,即行均值
print(arr.sum(axis=0))   # 跨行計算,即列和

常用數組統計方法:
在這裏插入圖片描述
True/False數組
計數:.sum():計算True的個數

arr = np.random.randn(100)
(arr > 0).sum()     # 56

.any(): 是否至少有一個True
.all(): 是否全爲True
非布爾值數組也適用,非0均爲True。

排序
.sort([axis]): 直接改變原數組,默認升序,可選參數axis表示按軸向
例如二維數組中 arr.sort(axis=1) :按列的方向,即對每一行排序。
np.sort(arr): 返回排好序的數組拷貝

集合操作:針對一維數組1d
np.unique(arr): 求arr中的唯一值(不重複的值),並排序,等價於sorted(set(arr))

arr = np.array(['a','b','b'])
print(np.unique(arr))  # ['a' 'b']
sorted(set(arr))       # ['a', 'b']

np.in1d(arr1,arr2): arr1中的值是否包含在arr2中,類似於R的%in%,返回同等大小的True/False數組。

其他集合操作 描述
intersect1d(x,y) 求交集,並排序
union1d(x,y) 求並集,並排序
setdiff1d(x,y) 求差集,在x中但不在y中的x元素
setxor1d(x,y) 求異或集,在x或y中,但不屬於交集的元素

數據在硬盤上的存取

np.save(路徑,arr): 將數組保存到硬盤,默認未壓縮,後綴.npy
np.load(路徑) :將數組載入
詳情見P116

線性代數

NumPy中矩陣*矩陣是逐元素相乘,因此dot()方法用於矩陣乘法。
x.dot(y) \Leftrightarrow np.dot(x,y) \Leftrightarrow x @ y:
如果是兩個向量,則返回其內積(一個數);如果是兩個矩陣,則返回矩陣的乘積。

x = np.array([[1,2,3],[4,5,6]])
y = np.array([[6,23],[-1,7],[8,9]])
x @ y

numpy.linalg擁有一個矩陣分解的標準函數集及矩陣常用函數
使用:np.linalg.inv(arr)
from numpy.linalg import inv,qr
在這裏插入圖片描述

僞隨機數生成numpy.random模塊

比Python內建的random模塊快了一個數量級
僞隨機數:根據算法由隨機數生成器中的隨機數種子生成的。
更改NumPy中的隨機數種子:np.random.seed(1234):使得隨機數據可預測。
在這裏插入圖片描述
注:上下限的區間均是不包含右端點

示例:隨機漫步

隨機漫步,從0開始,步進只能爲1或-1,二者發生概率相等,計算累積值。

nsteps = 1000  # 1000步
drows = np.random.randint(0,2,size=nsteps)  # 一次性生成1000個0,1
steps = np.where(drows == 0,-1,1)           # 把0全改爲-1
walk = steps.cumsum()                       # 計算步進的累積值
print(walk.min(),walk.max())                # -25 15
plt.plot(walk[:100])                        # 畫出前100步

在這裏插入圖片描述
何時第一次朝某個方向連續走了10步?

(np.abs(walk)>=10).argmax()-10     # 47
# 先得到走了超過10步的布爾數組,再計算第一個True的位置,
# 得到第一次走了10步的位置,-10得到何時開始走這10步
# argmax():返回最大值的第一個位置,在這裏True就是最大值,效率不高,因爲它首先要完整掃描整個數組
發佈了21 篇原創文章 · 獲贊 5 · 訪問量 1042
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章