跳至內容

用戶:Xyy23330121/Python/科學計算/數組

來自維基學院


數組是 numpy 中,表示矩陣或向量的工具。本章節的代碼均以下面代碼開頭。

import numpy as np

本章將講述數組作為容器對象的一些基本操作。

創建數組

[編輯 | 編輯原始碼]

最基本的創建數組的方法,是使用 np.array 從列表創建數組。

a = np.array([1,2,3,4,5,6])
b = np.array(
  [[1,2],
   [3,4],
   [5,6]]
)
c = np.array(
 [[[ 1, 2],
   [ 3, 4]],
  [[ 5, 6],
   [ 7, 8]],
  [[ 9,10],
   [11,12]]]
)

類似的,也可以使用 np.ndarray.tolist() 方法從數組創建列表。

數組的形狀

[編輯 | 編輯原始碼]

數組是具有形狀的,我們可以使用 shape,ndimsize屬性來確定數組的形狀。

#shape 代表数组的维数,以及每个维度的分量个数
print(a.shape)  #输出:(6, )
print(b.shape)  #输出:(3, 2)
print(c.shape)  #输出:(3, 2, 2)
#ndim 代表数组的维数
print(a.ndim)   #输出:1
print(b.ndim)   #输出:2
print(c.ndim)   #输出:3
#size 代表数组的总数据量
print(a.size)   #输出:6
print(b.size)   #输出:6
print(c.size)   #输出:12

數組與索引

[編輯 | 編輯原始碼]

一維數組

[編輯 | 編輯原始碼]

一維數組和列表使用相似的方法進行索引。

print(a[0])   #输出:1
print(a[0:])  #输出:[1 2 3 4 5 6]
print(a[:1])  #输出:[1]
print(a[2:4]) #输出:[3 4]
print(a[::2]) #输出:[1 3 5]

但需要注意,列表經 slice 索引時,創建的是切片部分的副本——更改副本不改變原列表的內容。而數組所創建的則是對原數組的引用——更改引用會更改原數組的內容。比如:

d = [1,2,3,4,5,6] #创建列表
d2 = d[2:4]
d2[0] = 9
print(d,d2)    #输出:[1, 2, 3, 4, 5, 6] [9, 4]

更改子列表副本,並未更改原列表的內容。而:

a2 = a[2:4]
a2[0] = 9
print(a,a2)    #输出:[1 2 9 4 5 6] [9 4]

原數組的內容也被更改。這是為了計算時方便而定的。

多維數組

[編輯 | 編輯原始碼]

多維數組的索引方式與多維列表相似,又有較大的不同。我們看以下示例:

print(b[0])     #输出:[1 2]
print(b[1,1])   #输出:4
print(b[1,:])   #输出:[3 4]
print(b[:,1])   #输出:[2 4 6]
print(c[1])     #输出:[[5 6]
                #       [7 8]]
print(c[1,1])   #输出:[7 8]
print(c[1,1,1]) #输出:9
print(c[1,:,1]) #输出:[6 8]

在進行索引時,與一維數組類似,如果索引得到的結果為 np.array 類型,則結果僅為原數組的引用,而非原數組的副本。

c1 = c[1,1]    #得到的对象类型:np.array
c1[1] = 9
print(c[1,1])  #输出:[7 9]
c2 = c[1,1,1]  #得到的对象类型:int
c2 = 8
print(c[1,1])  #输出:[7 9]

特殊索引方式

[編輯 | 編輯原始碼]

數組支持輸入一個由布爾值組成的數組作為其索引,比如:

a = np.array([1,2,3,4,5,6,7,8])
b = np.array([8,7,6,5,4,3,2,1])

#利用数组和整数的比较运算,创建由布尔值组成的数组。
#数组和数字,数组和数组的运算将在下一章讲解。数组内数据类型将在本页最下面讲解。
print(a<5)    #输出:[ True  True  True  True False False False False]

#用该数组进行索引。
print(a[a<5]) #输出:[1 2 3 4]
print(b[a<5]) #输出:[8 7 6 5]

此時,要求作為索引的布爾值數組,其size屬性和被索引數組的size屬性相等。

更多索引方式

[編輯 | 編輯原始碼]

參見:

調整數組的形狀

[編輯 | 編輯原始碼]

np.ndarray.reshape(shape) 方法會返回數組變形後的引用。數組變形前後各元素順序不變。

a = np.array([i for i in range(6)])
print(a)
#输出:[0 1 2 3 4 5]

b = a.reshape((2,3)) #变形

print(a)
#输出:[0 1 2 3 4 5]
#可见该方法并不改变原数组,而是返回了更改后的新的版本

print(b)
#输出:
#[[0 1 2]
# [3 4 5]]
#数字3依旧是数字2的下一个元素,元素顺序没有改变。

b[0,0] = 6
print(a)
#输出:[6 1 2 3 4 5]
#类似 数组与索引 章节的内容,变形后的数组并非副本,而是一个具有不同形状的引用。

更具體的用法,參見文檔:

以及相關內容:

特別的,np.ndarray.flatten() 方法會返回變形為一維的一個引用。它等同於:

a.reshape((a.size,))

a.T 屬性會返回原數組 a 的轉置。以三維數組為例,轉置會將原本索引為 [x, y, z] 的元素變更到索引為 [z, y, x] 的位置。我們測試以下的示例

a = np.array([i for i in range(30)])
a = a.reshape((2,3,5))

aT = a.T
result = True
for x in range(2):
    for y in range(3):
        for z in range(5):
            #对每个索引测试其元素
            result = (result and (a[x,y,z] == aT[z,y,x]))
print(result) #输出:True

aT[3,2,1] = 114
print(a[1,2,3]) #输出:114,可见转置生成的也是引用。

更多相關內容參見:

添加維度

[編輯 | 編輯原始碼]

除了 reshape 方法可以增加維度之外,numpy 額外提供了一種通過索引增加維度的方式。

print(np.newaxis is None)  #输出:True

a = np.array([0, 1, 2])
b = a[:, np.newaxis]
print(b)
#输出:
#[[0]
# [1]
# [2]]
# 为使 a[x] == b[x, 0] 的引用。

參見:

延申閱讀

[編輯 | 編輯原始碼]

以下文檔包含了更多更改數組形狀的方法:


特殊數組的創建

[編輯 | 編輯原始碼]

一些常用數組無需使用列表來創建,比如:

d = np.zeros(2)   #形状为(2, )的全零数组。
e = np.zeros(2,2) #形状为(2, 2)的全零数组。

f = np.ones(2)    #形状为(2, )的全一数组。
g = np.ones(2,2)  #形状为(2, 2)的全一数组。

除此之外,還有類似 slice 索引的:

h = np.arange(4)     #[0 1 2 3]
i = np.arange(2,4)   #[2 3]
j = np.arange(1,7,2) #[1 3 5]
k = np.arange(0, 1, 0.3) #[0 0.3 0.6 0.9]

以及用於線性採樣的:

l = np.linspace(0, 10, num=5) #5个数字组成的等差数组,起始为0,终止为10
                              #[0 2.5 5 7.5 10]
                              #即:在0~10之间取样5个点。

以下文檔提供了更多創建特殊數組的方法: