文章目錄
數組與向量化計算。優點:數組類型;快速的向量化計算(由於由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) # 返回服從標準正態分佈的樣本
# 參數是各維度大小,參數爲空時返回一個符合的實數
- 生成一維數組:從任意序列使用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])
- 生成多維數組,從嵌套序列轉換,幾重嵌套就是幾維
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
用場:
- 轉換爲數組時或生成數組時同時指定類型,通過參數dtype=
np.array(seq,dtype=)
np.empty(n,dtype=) - 顯式改變類型: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)
示例:根據網格數據計算
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) np.dot(x,y) 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就是最大值,效率不高,因爲它首先要完整掃描整個數組