NumPy陣列操作


NumPy - 陣列操作

NumPy包中有幾個例程用於處理ndarray物件中的元素。 它們可以分為以下型別:

修改形狀

序號 形狀及描述
1. reshape 不改變資料的條件下修改形狀
2. flat 陣列上的一維疊代器
3. flatten 返回摺疊為一維的陣列副本
4. ravel 返回連續的展開陣列

numpy.reshape

這個函式在不改變資料的條件下修改形狀,它接受如下引數:

numpy.reshape(arr, newshape, order')

其中:

  • arr:要修改形狀的陣列
  • newshape:整數或者整數陣列,新的形狀應當相容原有形狀
  • order'C'為 C 風格順序,'F'為 F 風格順序,'A'為保留原順序。

例子

import numpy as np
a = np.arange(8)
print '原始陣列:'
print a
print '\n'

b = a.reshape(4,2)
print '修改後的陣列:'
print b

輸出如下:

原始陣列:
[0 1 2 3 4 5 6 7]

修改後的陣列:
[[0 1]
 [2 3]
 [4 5]
 [6 7]]

numpy.ndarray.flat

該函式返回陣列上的一維疊代器,行為類似 Python 內建的疊代器。

例子

import numpy as np
a = np.arange(8).reshape(2,4)
print '原始陣列:'
print a
print '\n'

print '呼叫 flat 函式之後:'
# 返回展開陣列中的下標的對應元素
print a.flat[5]

輸出如下:

原始陣列:
[[0 1 2 3]
 [4 5 6 7]]

呼叫 flat 函式之後:
5

numpy.ndarray.flatten

該函式返回摺疊為一維的陣列副本,函式接受下列引數:

ndarray.flatten(order)

其中:

  • order'C' — 按行,'F' — 按列,'A' — 原順序,'k' — 元素在記憶體中的出現順序。

例子

import numpy as np
a = np.arange(8).reshape(2,4)

print '原陣列:'
print a
print '\n'  
# default is column-major

print '展開的陣列:'
print a.flatten()
print '\n'  

print '以 F 風格順序展開的陣列:'
print a.flatten(order = 'F')

輸出如下:

原陣列:
[[0 1 2 3]
 [4 5 6 7]]

展開的陣列:
[0 1 2 3 4 5 6 7]

以 F 風格順序展開的陣列:
[0 4 1 5 2 6 3 7]

numpy.ravel

這個函式返回展開的一維陣列,並且按需生成副本。返回的陣列和輸入陣列擁有相同資料型別。這個函式接受兩個引數。

numpy.ravel(a, order)

構造器接受下列引數:

  • order'C' — 按行,'F' — 按列,'A' — 原順序,'k' — 元素在記憶體中的出現順序。

例子

import numpy as np
a = np.arange(8).reshape(2,4)

print '原陣列:'
print a
print '\n'  

print '呼叫 ravel 函式之後:'
print a.ravel()  
print '\n'

print '以 F 風格順序呼叫 ravel 函式之後:'
print a.ravel(order = 'F')
原陣列:
[[0 1 2 3]
 [4 5 6 7]]

呼叫 ravel 函式之後:
[0 1 2 3 4 5 6 7]

以 F 風格順序呼叫 ravel 函式之後:
[0 4 1 5 2 6 3 7]

翻轉操作

序號 操作及描述
1. transpose 翻轉陣列的維度
2. ndarray.Tself.transpose()相同
3. rollaxis 向後捲動指定的軸
4. swapaxes 互換陣列的兩個軸

numpy.transpose

這個函式翻轉給定陣列的維度。如果可能的話它會返回一個檢視。函式接受下列引數:

numpy.transpose(arr, axes)

其中:

  • arr:要轉置的陣列
  • axes:整數的列表,對應維度,通常所有維度都會翻轉。

例子

import numpy as np
a = np.arange(12).reshape(3,4)

print '原陣列:'
print a  
print '\n'

print '轉置陣列:'
print np.transpose(a)

輸出如下:

原陣列:
[[ 0 1 2 3]
 [ 4 5 6 7]
 [ 8 9 10 11]]

轉置陣列:
[[ 0 4 8]
 [ 1 5 9]
 [ 2 6 10]
 [ 3 7 11]]

numpy.ndarray.T

該函式屬於ndarray類,行為類似於numpy.transpose

例子

import numpy as np
a = np.arange(12).reshape(3,4)

print '原陣列:'
print a
print '\n'  

print '轉置陣列:'
print a.T

輸出如下:

原陣列:
[[ 0 1 2 3]
 [ 4 5 6 7]
 [ 8 9 10 11]]

轉置陣列:
[[ 0 4 8]
 [ 1 5 9]
 [ 2 6 10]
 [ 3 7 11]]

numpy.rollaxis

該函式向後捲動特定的軸,直到一個特定位置。這個函式接受三個引數:

numpy.rollaxis(arr, axis, start)

其中:

  • arr:輸入陣列
  • axis:要向後捲動的軸,其它軸的相對位置不會改變
  • start:預設為零,表示完整的捲動。會捲動到特定位置。

例子

# 建立了三維的 ndarray
import numpy as np
a = np.arange(8).reshape(2,2,2)

print '原陣列:'
print a
print '\n'
# 將軸 2 捲動到軸 0(寬度到深度)

print '呼叫 rollaxis 函式:'
print np.rollaxis(a,2)  
# 將軸 0 捲動到軸 1:(寬度到高度)
print '\n'

print '呼叫 rollaxis 函式:'
print np.rollaxis(a,2,1)

輸出如下:

原陣列:
[[[0 1]
 [2 3]]
 [[4 5]
 [6 7]]]

呼叫 rollaxis 函式:
[[[0 2]
 [4 6]]
 [[1 3]
 [5 7]]]

呼叫 rollaxis 函式:
[[[0 2]
 [1 3]]
 [[4 6]
 [5 7]]]

numpy.swapaxes

該函式交換陣列的兩個軸。對於 1.10 之前的 NumPy 版本,會返回交換後陣列的試圖。這個函式接受下列引數:

numpy.swapaxes(arr, axis1, axis2)
  • arr:要交換其軸的輸入陣列
  • axis1:對應第一個軸的整數
  • axis2:對應第二個軸的整數
# 建立了三維的 ndarray
import numpy as np
a = np.arange(8).reshape(2,2,2)

print '原陣列:'
print a
print '\n'  
# 現在交換軸 0(深度方向)到軸 2(寬度方向)

print '呼叫 swapaxes 函式後的陣列:'
print np.swapaxes(a, 2, 0)

輸出如下:

原陣列:
[[[0 1]
 [2 3]]

 [[4 5]
  [6 7]]]

呼叫 swapaxes 函式後的陣列:
[[[0 4]
 [2 6]]

 [[1 5]
  [3 7]]]

修改維度

序號 維度和描述
1. broadcast 產生模仿廣播的物件
2. broadcast_to 將陣列廣播到新形狀
3. expand_dims 擴充套件陣列的形狀
4. squeeze 從陣列的形狀中刪除單維條目

broadcast

如前所述,NumPy 已經內建了對廣播的支援。 此功能模仿廣播機制。 它返回一個物件,該物件封裝了將一個陣列廣播到另一個陣列的結果。

該函式使用兩個陣列作為輸入引數。 下面的例子說明了它的用法。

import numpy as np
x = np.array([[1], [2], [3]])
y = np.array([4, 5, 6])  

# 對 y 廣播 x
b = np.broadcast(x,y)  
# 它擁有 iterator 屬性,基於自身元件的疊代器元組

print '對 y 廣播 x:'
r,c = b.iters
print r.next(), c.next()
print r.next(), c.next()
print '\n'  
# shape 屬性返回廣播物件的形狀

print '廣播物件的形狀:'
print b.shape
print '\n'  
# 手動使用 broadcast 將 x 與 y 相加
b = np.broadcast(x,y)
c = np.empty(b.shape)

print '手動使用 broadcast 將 x 與 y 相加:'
print c.shape
print '\n'  
c.flat = [u + v for (u,v) in b]

print '呼叫 flat 函式:'
print c
print '\n'  
# 獲得了和 NumPy 內建的廣播支援相同的結果

print 'x 與 y 的和:'
print x + y

輸出如下:

對 y 廣播 x:
1 4
1 5

廣播物件的形狀:
(3, 3)

手動使用 broadcast 將 x 與 y 相加:
(3, 3)

呼叫 flat 函式:
[[ 5. 6. 7.]
 [ 6. 7. 8.]
 [ 7. 8. 9.]]

x 與 y 的和:
[[5 6 7]
 [6 7 8]
 [7 8 9]]

numpy.broadcast_to

此函式將陣列廣播到新形狀。 它在原始陣列上返回唯讀檢視。 它通常不連續。 如果新形狀不符合 NumPy 的廣播規則,該函式可能會丟擲ValueError

注意 - 此功能可用於 1.10.0 及以後的版本。

該函式接受以下引數。

numpy.broadcast_to(array, shape, subok)

例子

import numpy as np
a = np.arange(4).reshape(1,4)

print '原陣列:'
print a
print '\n'  

print '呼叫 broadcast_to 函式之後:'
print np.broadcast_to(a,(4,4))

輸出如下:

[[0  1  2  3]
 [0  1  2  3]
 [0  1  2  3]
 [0  1  2  3]]

numpy.expand_dims

函式通過在指定位置插入新的軸來擴充套件陣列形狀。該函式需要兩個引數:

numpy.expand_dims(arr, axis)

其中:

  • arr:輸入陣列
  • axis:新軸插入的位置

例子

import numpy as np
x = np.array(([1,2],[3,4]))

print '陣列 x:'
print x
print '\n'  
y = np.expand_dims(x, axis = 0)

print '陣列 y:'
print y
print '\n'

print '陣列 x 和 y 的形狀:'
print x.shape, y.shape
print '\n'  
# 在位置 1 插入軸
y = np.expand_dims(x, axis = 1)

print '在位置 1 插入軸之後的陣列 y:'
print y
print '\n'  

print 'x.ndim 和 y.ndim:'
print x.ndim,y.ndim
print '\n'  

print 'x.shape 和 y.shape:'
print x.shape, y.shape

輸出如下:

陣列 x:
[[1 2]
 [3 4]]

陣列 y:
[[[1 2]
 [3 4]]]

陣列 x 和 y 的形狀:
(2, 2) (1, 2, 2)

在位置 1 插入軸之後的陣列 y:
[[[1 2]]
 [[3 4]]]

x.shape 和 y.shape:
2 3

x.shape and y.shape:
(2, 2) (2, 1, 2)

numpy.squeeze

函式從給定陣列的形狀中刪除一維條目。 此函式需要兩個引數。

numpy.squeeze(arr, axis)

其中:

  • arr:輸入陣列
  • axis:整數或整數元組,用於選擇形狀中單一維度條目的子集

例子

import numpy as np  
x = np.arange(9).reshape(1,3,3)

print '陣列 x:'
print x
print '\n'  
y = np.squeeze(x)

print '陣列 y:'
print y
print '\n'  

print '陣列 x 和 y 的形狀:'
print x.shape, y.shape

輸出如下:

陣列 x:
[[[0 1 2]
 [3 4 5]
 [6 7 8]]]

陣列 y:
[[0 1 2]
 [3 4 5]
 [6 7 8]]

陣列 x 和 y 的形狀:
(1, 3, 3) (3, 3)

陣列的連線

序號 陣列及描述
1. concatenate 沿著現存的軸連線資料序列
2. stack 沿著新軸連線陣列序列
3. hstack 水平堆疊序列中的陣列(列方向)
4. vstack 豎直堆疊序列中的陣列(行方向)

numpy.concatenate

陣列的連線是指連線。 此函式用於沿指定軸連線相同形狀的兩個或多個陣列。 該函式接受以下引數。

numpy.concatenate((a1, a2, ...), axis)

其中:

  • a1, a2, ...:相同型別的陣列序列
  • axis:沿著它連線陣列的軸,預設為 0

例子

import numpy as np
a = np.array([[1,2],[3,4]])

print '第一個陣列:'
print a
print '\n'  
b = np.array([[5,6],[7,8]])

print '第二個陣列:'
print b
print '\n'  
# 兩個陣列的維度相同

print '沿軸 0 連線兩個陣列:'
print np.concatenate((a,b))
print '\n'  

print '沿軸 1 連線兩個陣列:'
print np.concatenate((a,b),axis = 1)

輸出如下:

第一個陣列:
[[1 2]
 [3 4]]

第二個陣列:
[[5 6]
 [7 8]]

沿軸 0 連線兩個陣列:
[[1 2]
 [3 4]
 [5 6]
 [7 8]]

沿軸 1 連線兩個陣列:
[[1 2 5 6]
 [3 4 7 8]]

numpy.stack

此函式沿新軸連線陣列序列。 此功能新增自 NumPy 版本 1.10.0。 需要提供以下引數。

numpy.stack(arrays, axis)

其中:

  • arrays:相同形狀的陣列序列
  • axis:返回陣列中的軸,輸入陣列沿著它來堆疊
import numpy as np
a = np.array([[1,2],[3,4]])

print '第一個陣列:'
print a
print '\n'
b = np.array([[5,6],[7,8]])

print '第二個陣列:'
print b
print '\n'  

print '沿軸 0 堆疊兩個陣列:'
print np.stack((a,b),0)
print '\n'  

print '沿軸 1 堆疊兩個陣列:'
print np.stack((a,b),1)

輸出如下:

第一個陣列:
[[1 2]
 [3 4]]

第二個陣列:
[[5 6]
 [7 8]]

沿軸 0 堆疊兩個陣列:
[[[1 2]
 [3 4]]
 [[5 6]
 [7 8]]]

沿軸 1 堆疊兩個陣列:
[[[1 2]
 [5 6]]
 [[3 4]
 [7 8]]]

numpy.hstack

numpy.stack函式的變體,通過堆疊來生成水平的單個陣列。

例子

import numpy as np
a = np.array([[1,2],[3,4]])

print '第一個陣列:'
print a
print '\n'  
b = np.array([[5,6],[7,8]])

print '第二個陣列:'
print b
print '\n'  

print '水平堆疊:'
c = np.hstack((a,b))
print c
print '\n'

輸出如下:

第一個陣列:
[[1 2]
 [3 4]]

第二個陣列:
[[5 6]
 [7 8]]

水平堆疊:
[[1 2 5 6]
 [3 4 7 8]]

numpy.vstack

numpy.stack函式的變體,通過堆疊來生成豎直的單個陣列。

import numpy as np
a = np.array([[1,2],[3,4]])

print '第一個陣列:'
print a
print '\n'  
b = np.array([[5,6],[7,8]])

print '第二個陣列:'
print b
print '\n'

print '豎直堆疊:'
c = np.vstack((a,b))
print c

輸出如下:

第一個陣列:
[[1 2]
 [3 4]]

第二個陣列:
[[5 6]
 [7 8]]

豎直堆疊:
[[1 2]
 [3 4]
 [5 6]
 [7 8]]

陣列分割

序號 陣列及操作
1. split 將一個陣列分割為多個子陣列
2. hsplit 將一個陣列水平分割為多個子陣列(按列)
3. vsplit 將一個陣列豎直分割為多個子陣列(按行)

numpy.split

該函式沿特定的軸將陣列分割為子陣列。函式接受三個引數:

numpy.split(ary, indices_or_sections, axis)

其中:

  • ary:被分割的輸入陣列
  • indices_or_sections:可以是整數,表明要從輸入陣列建立的,等大小的子陣列的數量。 如果此引數是一維陣列,則其元素表明要建立新子陣列的點。
  • axis:預設為 0

例子

import numpy as np
a = np.arange(9)

print '第一個陣列:'
print a
print '\n'  

print '將陣列分為三個大小相等的子陣列:'
b = np.split(a,3)
print b
print '\n'  

print '將陣列在一維陣列中表明的位置分割:'
b = np.split(a,[4,7])
print b

輸出如下:

第一個陣列:
[0 1 2 3 4 5 6 7 8]

將陣列分為三個大小相等的子陣列:
[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]

將陣列在一維陣列中表明的位置分割:
[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]

numpy.hsplit

numpy.hsplitsplit()函式的特例,其中軸為 1 表示水平分割,無論輸入陣列的維度是什麼。

import numpy as np
a = np.arange(16).reshape(4,4)

print '第一個陣列:'
print a
print '\n'  

print '水平分割:'
b = np.hsplit(a,2)
print b
print '\n'

輸出:

第一個陣列:
[[ 0 1 2 3]
 [ 4 5 6 7]
 [ 8 9 10 11]
 [12 13 14 15]]

水平分割:                                                         
[array([[ 0,  1],                                                             
       [ 4,  5],                                                              
       [ 8,  9],                                                              
       [12, 13]]), array([[ 2,  3],                                           
       [ 6,  7],                                                              
       [10, 11],                                                              
       [14, 15]])]

numpy.vsplit

numpy.vsplitsplit()函式的特例,其中軸為 0 表示豎直分割,無論輸入陣列的維度是什麼。下面的例子使之更清楚。

import numpy as np
a = np.arange(16).reshape(4,4)

print '第一個陣列:'
print a
print '\n'

print '豎直分割:'
b = np.vsplit(a,2)
print b

輸出如下:

第一個陣列:
[[ 0 1 2 3]
 [ 4 5 6 7]
 [ 8 9 10 11]
 [12 13 14 15]]

豎直分割:                                                           
[array([[0, 1, 2, 3],                                                         
       [4, 5, 6, 7]]), array([[ 8,  9, 10, 11],                               
       [12, 13, 14, 15]])]

新增/刪除元素

序號 元素及描述
1. resize 返回指定形狀的新陣列
2. append 將值新增到陣列末尾
3. insert 沿指定軸將值插入到指定下標之前
4. delete 返回刪掉某個軸的子陣列的新陣列
5. unique 尋找陣列內的唯一元素

numpy.resize

此函式返回指定大小的新陣列。 如果新大小大於原始大小,則包含原始陣列中的元素的重複副本。 該函式接受以下引數。

numpy.resize(arr, shape)

其中:

  • arr:要修改大小的輸入陣列
  • shape:返回陣列的新形狀

例子

import numpy as np
a = np.array([[1,2,3],[4,5,6]])

print '第一個陣列:'
print a
print '\n'

print '第一個陣列的形狀:'
print a.shape
print '\n'  
b = np.resize(a, (3,2))

print '第二個陣列:'
print b
print '\n'  

print '第二個陣列的形狀:'
print b.shape
print '\n'  
# 要注意 a 的第一行在 b 中重複出現,因為尺寸變大了

print '修改第二個陣列的大小:'
b = np.resize(a,(3,3))
print b

輸出如下:

第一個陣列:
[[1 2 3]
 [4 5 6]]

第一個陣列的形狀:
(2, 3)

第二個陣列:
[[1 2]
 [3 4]
 [5 6]]

第二個陣列的形狀:
(3, 2)

修改第二個陣列的大小:
[[1 2 3]
 [4 5 6]
 [1 2 3]]

numpy.append

此函式在輸入陣列的末尾新增值。 附加操作不是原地的,而是分配新的陣列。 此外,輸入陣列的維度必須匹配否則將生成ValueError

函式接受下列函式:

numpy.append(arr, values, axis)

其中:

  • arr:輸入陣列
  • values:要向arr新增的值,比如和arr形狀相同(除了要新增的軸)
  • axis:沿著它完成操作的軸。如果沒有提供,兩個引數都會被展開。

例子

import numpy as np
a = np.array([[1,2,3],[4,5,6]])

print '第一個陣列:'
print a
print '\n'  

print '向陣列新增元素:'
print np.append(a, [7,8,9])
print '\n'  

print '沿軸 0 新增元素:'
print np.append(a, [[7,8,9]],axis = 0)
print '\n'  

print '沿軸 1 新增元素:'
print np.append(a, [[5,5,5],[7,8,9]],axis = 1)

輸出如下:

第一個陣列:
[[1 2 3]
 [4 5 6]]

向陣列新增元素:
[1 2 3 4 5 6 7 8 9]

沿軸 0 新增元素:
[[1 2 3]
 [4 5 6]
 [7 8 9]]

沿軸 1 新增元素:
[[1 2 3 5 5 5]
 [4 5 6 7 8 9]]

numpy.insert

此函式在給定索引之前,沿給定軸在輸入陣列中插入值。 如果值的型別轉換為要插入,則它與輸入陣列不同。 插入沒有原地的,函式會返回一個新陣列。 此外,如果未提供軸,則輸入陣列會被展開。

insert()函式接受以下引數:

numpy.insert(arr, obj, values, axis)

其中:

  • arr:輸入陣列
  • obj:在其之前插入值的索引
  • values:要插入的值
  • axis:沿著它插入的軸,如果未提供,則輸入陣列會被展開

例子

import numpy as np
a = np.array([[1,2],[3,4],[5,6]])

print '第一個陣列:'
print a
print '\n'  

print '未傳遞 Axis 引數。 在插入之前輸入陣列會被展開。'
print np.insert(a,3,[11,12])
print '\n'  
print '傳遞了 Axis 引數。 會廣播值陣列來配輸入陣列。'

print '沿軸 0 廣播:'
print np.insert(a,1,[11],axis = 0)
print '\n'  

print '沿軸 1 廣播:'
print np.insert(a,1,11,axis = 1)

numpy.delete

此函式返回從輸入陣列中刪除指定子陣列的新陣列。 與insert()函式的情況一樣,如果未提供軸引數,則輸入陣列將展開。 該函式接受以下引數:

Numpy.delete(arr, obj, axis)

其中:

  • arr:輸入陣列
  • obj:可以被切片,整數或者整數陣列,表明要從輸入陣列刪除的子陣列
  • axis:沿著它刪除給定子陣列的軸,如果未提供,則輸入陣列會被展開

例子

import numpy as np
a = np.arange(12).reshape(3,4)

print '第一個陣列:'
print a
print '\n'  

print '未傳遞 Axis 引數。 在插入之前輸入陣列會被展開。'
print np.delete(a,5)
print '\n'  

print '刪除第二列:'  
print np.delete(a,1,axis = 1)
print '\n'  

print '包含從陣列中刪除的替代值的切片:'
a = np.array([1,2,3,4,5,6,7,8,9,10])
print np.delete(a, np.s_[::2])

輸出如下:

第一個陣列:
[[ 0 1 2 3]
 [ 4 5 6 7]
 [ 8 9 10 11]]

未傳遞 Axis 引數。 在插入之前輸入陣列會被展開。
[ 0 1 2 3 4 6 7 8 9 10 11]

刪除第二列:
[[ 0 2 3]
 [ 4 6 7]
 [ 8 10 11]]

包含從陣列中刪除的替代值的切片:
[ 2 4 6 8 10]

numpy.unique

此函式返回輸入陣列中的去重元素陣列。 該函式能夠返回一個元組,包含去重陣列和相關索引的陣列。 索引的性質取決於函式呼叫中返回引數的型別。

numpy.unique(arr, return_index, return_inverse, return_counts)

其中:

  • arr:輸入陣列,如果不是一維陣列則會展開
  • return_index:如果為true,返回輸入陣列中的元素下標
  • return_inverse:如果為true,返回去重陣列的下標,它可以用於重構輸入陣列
  • return_counts:如果為true,返回去重陣列中的元素在原陣列中的出現次數

例子

import numpy as np
a = np.array([5,2,6,2,7,5,6,8,2,9])

print '第一個陣列:'
print a
print '\n'  

print '第一個陣列的去重值:'
u = np.unique(a)
print u
print '\n'  

print '去重陣列的索引陣列:'
u,indices = np.unique(a, return_index = True)
print indices
print '\n'  

print '我們可以看到每個和原陣列下標對應的數值:'
print a
print '\n'  

print '去重陣列的下標:'
u,indices = np.unique(a,return_inverse = True)
print u
print '\n'

print '下標為:'
print indices
print '\n'  

print '使用下標重構原陣列:'
print u[indices]
print '\n'  

print '返回去重元素的重複數量:'
u,indices = np.unique(a,return_counts = True)
print u
print indices

輸出如下:

第一個陣列:
[5 2 6 2 7 5 6 8 2 9]

第一個陣列的去重值:
[2 5 6 7 8 9]

去重陣列的索引陣列:
[1 0 2 4 7 9]

我們可以看到每個和原陣列下標對應的數值:
[5 2 6 2 7 5 6 8 2 9]

去重陣列的下標:
[2 5 6 7 8 9]

下標為:
[1 0 2 0 3 1 2 4 0 5]

使用下標重構原陣列:
[5 2 6 2 7 5 6 8 2 9]

返回唯一元素的重複數量:
[2 5 6 7 8 9]
 [3 2 2 1 1 1]