NumPy

NumPy
  • NumPy是Numeric Python的簡稱
  • NumPy是Python科學計算的基礎工具包
  • NumPy是Python數值計算擴展,專門用于處理矩陣,其運算效率比列表更高效。
  • NumPy底層使用C編寫,能高效地執行數值計算。

隨著數據科學(Data Science,DS)發展,科學計算、數據處理等數據分析庫大量增長。在矩陣乘法和數組形狀處理上,NumPy具有較好的優勢。

  • 數組算數、邏輯運算
  • 傅里葉變換、圖形操作
  • 線性代數操作

NumPy通常會與SciPy和Matplotlib繪圖庫組合使用,此組合廣泛用于替代MatLab,是一種流行的技術計算平臺。

學習資料

安裝

查看是否安裝

  • NumPy作為Python的第三方擴展庫,沒有包含在標準庫中,因此需要獨立安裝。
$ pip list | grep numpy
numpy                              1.20.3
numpydoc                           1.1.0

$ pip install numpy

檢測安裝版本

import numpy as np
print(np.__version__)

實際項目中NumPy與SciPy會一起使用,SciPy可看作是NumPy的擴展。

ndarray

數組是元素或值的集合,可具有多個維度。通常一維數組稱為向量,二維數組稱為矩陣。

  • NumPy的數據結構是n維的數組對象ndarray,Python的list雖然也能表示但不高效,隨著列表數據的增加效率會降低。
  • NumPy的ndarray是一個由一系列相同類型的元素組成的數組集合,以0下標為開始進行集合中元素的索引。
  • ndarray數組中的每個元素都占有大小相同的內存塊,因此可直接使用索引或切片的方式來訪問。
  • ndarray對象采用了數組的索引機制,將數組元素映射到內存塊上,并按一定的布局對內存塊進行排列。常見的布局方式分為按行或按列。

內存結構

  • 一個指向數據的指針,內存或內存映射文件中的一塊數據。
  • 數據類型dtype,描述在數組中固定大小值的格子。
  • 一個表示數組型形狀shape的元組,表示各個維度大小的元組。
  • 一個跨度元素stride,整數表示為了前進到下一個元素需要跨過的字節數。跨度可以是負數,負數可以使數組在內存中向后移動,切片中obj[::-1]obj[:, ::-1]即如此。
ndarray

Python本身執行是慢的,因為會執行很多復雜的check功能,而調用NumPy時其實調用調用的是C語言而非Python。NumPy其實是C的邏輯,例如創建存儲容器array是會尋找內存上一連串區域來存放,而Python存放的原則是不連續的區域。這使得Python在索引容器中的數據時不會那么高效。Numpy只需要在固定的連續區域前后游走就能拿到數據。

NumPy通常不是用一個一維數組來存放數據,而是用二維或三維的塊來存放,NumPy快速的矩陣相乘運算,能將乘法運算分配到計算機的多核上來并行運算來加速運算速度。

創建

  • NumPy內置函數array()可創建ndarray對象
numpy.array( object, dtype = None, copy = True, order = None, subok = False, ndim = 8)
構造參數 必填 描述
object 必須 任何暴露數組接口方法的對象都會返回一個數組或任意嵌套序列
dtype 可選 數組所需的數據類型
copy 可選 對象是否被復制
order 可選 排序類型,C按行/F按列/A任意(默認)。
subok 可選 默認返回的數組會被強制為基類數組,若subok為true則為子類。
ndim 可選 數組的最小維度

例如:創建一維數組并獲取類型

import numpy as np

nda = np.array([1, 2, 3])
print(nda)
print(type(nda))
[1 2 3]
<class 'numpy.ndarray'>

例如:創建多維數組并轉化為復數類型

import numpy as np

lst = [
    [1, 2, 3],
    [10, 20, 30]
]
nda = np.array(lst, dtype = 'complex')
print(nda)

NumPy中主要的數據對象是具有相同數據類型的多維數組,所有元素都具有相同數據類型,通過一個正整數元素索引的元素表格,通常元素是數字。

例如:使用NumPy中的array函數將系統自帶的列表list轉換成為NumPy中的數組,嵌套列表會被轉換為多維數組(矩陣)。

import numpy as np

lst = [[1, 3, 5], [2, 4, 6]]
arr = np.array(lst)
array([
  [1, 3, 5],
  [2, 4, 6]
])

NumPy中array數組內部的元素必須為相同類型,可使用dtype指令查看類型。

import numpy as np

lst = [[1, 3, 5], [2, 4, 6]]
arr = np.array(lst)
arr.dtype
dtype('int32')

通常數組元素開始都是未知的,但大小已知。因此NumPy使用占位符創建數組的函數。

數據類型

NumPy支持的數據類型比Python內置的要多,基本和C語言的數據類型對應。

數據類型 描述
bool_ 布爾類型,值為TrueFalse
int_ 模型整型,類似C中的longint32int64
intc 類似C中的int類型,一般為int32int64
intp 用于索引的整型,類似C中的ssize_t,一般為int32int64
int8 字節,數據范圍-127~127
int16 整型,數據范圍-32768~32767
int32 整型
int64 整型
uint8 無符號整數
uint16 無符號整數
uint32 無符號整數
uint64 無符號整數
float_ float64類型縮寫
float16 半精度浮點數
float32 單精度浮點數
float64 雙精度浮點數
complex_ complex128類型的簡寫,即128位復數。
complex64 復數,雙32位浮點數,實數部分和虛數部分。
complex128 復數,雙64位浮點數,實數部分和虛數部分。

數據類型對象dtype

  • dtype是數據類型對象numpy.dtype類的實例
  • dtype用來描述與數組對應的內存區域是如何使用的

dtype描述了數據的以下方面

  • 數據的類型,比如整數、浮點數、Python對象。
  • 數據的大小,比如整數使用多少個字節存儲。
  • 數據的字節順序,比如大端法或小端法。
  • 結構化類型下,字段的名稱、每個字段的數據類型、每個字段所取的內存塊的部分。
  • 若數據類型是子數組則形狀和數據類型是什么

每個內置類型都具有唯一的字符代碼

類型代碼 數據類型
b 布爾類型
i 有符號整型
u 無符號整型
f 浮點型
c 復數浮點型
m 時間間隔timedelta
M 日期時間datetime
O Python對象
S 字符串
a 字節byte
U Unicode
V 原始類型void

語法結構

numpy.dtype(object, align, copy)
參數 描述
object 需要轉換為的數據類型對象
align 填充字段是否使用類似C的結構體
copy 是否復制dtype對象,若為false則是對內置數據類型對象的引用。

例如:定義結構化數據類型user,包含字符串字段name、整型字段id、浮點型字段salary,并將dtype應用到數組對象中。

import numpy as np

dt = np.dtype([
    ('id', np.int8),
    ('name', 'S20'),
    ('salary', 'f4')
])
print(dt) # [('id', 'i1'), ('name', 'S20'), ('salary', '<f4')]

arr = np.array([
    (1, 'alice', 4500), 
    (2, 'bob', 8700), 
    (3, 'carl', 9500)
], dtype = dt)

print(arr) # [(1, b'alice', 4500.) (2, b'bob', 8700.) (3, b'carl', 9500.)]

數據類型對象

  • NumPy的數組ndarray,與標準Python類庫array.array不同。它提供了比Python更更富的數據類型。

數據類型對象

數據類型對象(Data Type Object)又稱為dtype對象,主要用來描述數組元素的數據類型、大小、字節順序等。同時也可以用來創建結構化數據。

例如:創建int64類型的數組

import numpy as np

dto = np.dtype(np.int64)
print(dto) # int64

數據類型標識碼

  • NumPy每種數據類型都具有一個唯一標識的字符碼
  • 可使用數據類型標識碼創建結構化數據
import numpy as np

dto = np.dtype([('score', 'i1')])
print(dto) # [('score', 'i1')]

例如:使用數據類型標識碼

import numpy as np

dto = np.dtype([('score', 'i1')])

data = [
    (10,),
    (20,),
    (30,)
]
a = np.array(data, dtype = dto)

print(a) # [(10,) (20,) (30,)]
print(a.dtype) # [('score', 'i1')]
print(a['score']) # [10 20 30]

例如:定義結構化數據,結構化數據使用字段的形式來描述某個對象的特征。

import numpy as np

dto = np.dtype([('name', 'S20'), ('gender', 'i1'), ('salary', 'f4')])

data = [
    ('alice', 1, 9000.00),
    ('job', 2, 6500.00),
    ('carl', 1, 4000.00)
]
arr = np.array(data, dtype = dto)

print(arr) # [(b'alice', 1, 9000.) (b'job', 2, 6500.) (b'carl', 1, 4000.)]

屬性

  • NumPy數組的維數稱為秩rank,秩的數量就是軸的數量,也就是數組的維度。
    比如一維數組的秩為1,二維數組的秩為2,以此類推。
  • NumPy中每個線性的數組稱為一個軸Zaxis,也就是維度dimensions
    比如二維數組相當于兩個一維數組,第一個一維數組中的每個元素又是一個一維數組。,所以一維數組是NumPy的軸,第一個軸相當于是底層數組,第二個軸是底層數組中的數組,軸的數量有也就是秩,即數組的維數。
屬性 數組 描述
數組的維度 形狀
數組的維數 軸的數量
屬性

例如:NumPy中維度(dimensions)叫做軸(axies),軸的個數稱為秩(rank)。

[1, 2, 3]

例如:3D空間中的一個點的坐標[1, 2, 3]是一個秩為1的數組(一個維度),它只有一個軸。軸的長度為3。

[[1., 0., 0.], [0., 1., 2.]]

數組的秩為2,具有兩個維度,第一個維度長度為2,第二個維度長度為3。

屬性 描述
ndarray.ndim 數組的維數
ndarray.shape 數組的維度,返回由數組維度構成的元組,可用來調整數組形狀。
ndarray.size 數組元素總個數
ndarray.itemsize 數組中每個元素的字節大小
ndarray.dtype 數據中元素類型的對象
ndarray.data 實際數組元素的緩沖區
ndarray.flags ndarray數組內存信息

例如:生成3x5二維數組后獲取屬性

from numpy import *
arr = arange(15).reshape(3, 5)
print(arr)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
print(arr.ndim) # 2
print(arr.shape) # (3, 5)
print(arr.dtype.name) # int32
print(arr.itemsize) # 4
print(arr.size) # 15
print(type(arr)) # <class 'numpy.ndarray'>

維數ndim

  • 獲取數組的維數,即秩rank

例如:使用ndim屬性查看數組維數

import numpy as np

lst = [
    [1, 2, 3],
    [10, 20, 30]
]
nda = np.array(lst, dtype = 'complex')
print(nda.ndim) # 2

例如:指定維數創建數組,報錯。

import numpy as np

lst = [1, 2, 3]
nda = np.array(lst, ndim=2)
print(nda)
TypeError: 'ndim' is an invalid keyword argument for array()

形狀shape

  • ndarray.shape表示數組的維度,返回一個元組。
  • 元素的長度也就是維度的數量,即ndim屬性的值(秩)。
    例如:一個二維數組,其維度表示為行數和列數
import numpy as np

arr = np.array([
    [1, 2, 3],
    [4, 5, 6]
])
print(arr.shape) # (2, 3)
  • ndarray.shape可用于調整數組大小
arr.shape = (3, 2)
print(arr)
[[1 2]
 [3 4]
 [5 6]]
  • NumPy也專門提供了reshape()方法來調整數組的形狀,即數組變維。

數組變維rechape()

  • 數組形狀是指多維數組的行數和列數,數組變維實際上是對數組形狀的重塑。
  • NumPy提供了reshape()函數用來改變多維數組行數和列表,從而達到數組變維的目的。
  • reshape()通常返回的是非拷貝副本,改變返回數組的元素后原數組對應元素的值也會改變。
數組變維
import numpy as np

arr = np.array([[1, 2], [3, 4], [5, 6]])
ary = arr.reshape(2, 3)
print(ary)
[[1 2 3]
 [4 5 6]]

元素大小itemsize

  • ndarray.itemsize屬性會以字節形式返回數組中每個元素的大小

例如:類型為float64的數組的itemsize為8,因為float64占64個bits,每個字節長度為8,因此占8個字節。

import numpy as np

arr = np.array([1, 1.1, 2.2], dtype = np.float64)
print(arr.itemsize) # 8

內存信息flags

  • nparray.flags屬性會返回數組對象的內存信息

例如:獲取數組內存信息

import numpy as np

arr = np.array([1, 1.1, 2.2], dtype = np.float64)
print(arr.flags)
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False
內存信息 簡稱 描述
C_CONTIGUOUS C 數據在一個單一的C風格的連續段上
F_CONTIGUOUS F 數據在一個單一的Fortran風格的連續段中
OWNDATA O 數組擁有它所使用的內存,或從另一個對象中借用它。
WRITSBLE W 數據區域可以被寫入,設置為False則數據為只讀。
ALIGNED A 數據和所有元素都適當對齊到硬件上
UPDATEIFCOPY U 數組是其他數組的一個副本,當數組被釋放時源數組內容將被更新。

方法

函數 描述
zeros() 創建元素全是0的數組
ones() 創建元素全是1的數組
empty() 創建內容隨機且以來內存狀態的數組

例如:

from numpy import *
print( zeros( (3,4) ) )
print( ones( (2,3,4), dtype=int16 ) )
print( empty( (2,3) ) )

創建數列

  • NumPy提供了類似arange函數用于返回數組而非列表
from numpy import *
arange( 10, 30, 5 )
array([10, 15, 20, 25])

數組計算

  • 數組計算無需循環即可批量運算
import numpy as np
lst = [[1, 3, 5], [2, 4, 6]]
arr = np.array(lst)
print(arr)
print(arr + 1)
print(arr - 1)
print(arr * 2)
print(arr * arr)
[[1 3 5]
 [2 4 6]]

[[2 4 6]
 [3 5 7]]

[[0 2 4]
 [1 3 5]]

[[ 2  6 10]
 [ 4  8 12]]

[[ 1  9 25]
 [ 4 16 36]]

數組賦值

  • 數組索引和列表相同,可通過方括號[]和數字選擇,也可直接賦值。
import numpy as np
lst = [[1, 3, 5], [2, 4, 6]]
arr = np.array(lst)

print(arr[1])

print(arr[1][1])

print(arr[-1:])

arr[0] = [10, 30, 50]
print(arr[0])
[2 4 6]
4
[[2 4 6]]
[10 30 50]

空數組empty()

NumPy提供了empty()方法來創建一個指定形狀shape和數據類型dtype,但未初始化的空數組。由于未初始化,因此元素值會是隨機數。

numpy.empty(shape, dtype = float, order = 'C')
屬性 描述
shape 數組形狀
dtype 數據類型,可選。
order 內存中存儲元素的順序,C表示行優先,F表示列優先。
排序 描述
C 行優先,用于C的行數組。
F 列優先,用于Fortan的列數組。

例如:創建一個2行3列的二維空數組

import numpy as np

arr = np.empty([2, 3], dtype = int)
print(arr)
[
    [          0  1072693248 -1717986918]
    [ 1072798105 -1717986918  1073846681]
]

零數組zeros()

NumPy提供的zeros()方法可用來創建指定形狀的且使用0填充的數組

numpy.zeros(shape, dtype = float, order = 'C')
屬性 描述
shape 數組形狀
dtype 數據類型,可選。
order 內存存儲元素的排序方式
import numpy as np

arr = np.zeros(3)
print(arr) # [0. 0. 0.]
arr = np.zeros((3,), dtype = np.int32)
print(arr) # [0 0 0]
arr = np.zeros((2,2), dtype = [('x', 'i4'), ('y', 'f4')])
print(arr)
[
    [(0, 0.) (0, 0.)]
     [(0, 0.) (0, 0.)]
]

壹數組ones()

NumPy提供的ones()方法用于創建指定形狀且元素以1來填充的數組

numpy.ones(shape, dtype = None, order = 'C')

例如:

import numpy as np

arr = np.ones(3)
print(arr) # [1. 1. 1.]
arr = np.ones((3,), dtype = np.int32)
print(arr) # [1 1 1]
arr = np.ones((2,2), dtype = [('x', 'i4'), ('y', 'f4')])
print(arr)
[
    [(1, 1.) (1, 1.)]
    [(1, 1.) (1, 1.)]
]

區間數組

區間數組是指數組元素的取值位于某個范圍內,元素之間呈現出某種規律,比如等比、遞增、遞減等。

區間數組 描述
numpy.arange() 生成普通數列
numpy.linspace() 生成等差數列
numpy.logspace() 生成等比數列

numpy.arange()函數可根據start開始和stop結束指定的范圍,以及step步長來生成一個ndarray的數組。

numpy.arange(start, stop, step, dtype)
參數 描述
start 起始值,默認為0。
stop 終止值,生成的ndarray中的元素不包含終止值。
step 步長,默認為1。
dtype 可選,指定生成ndarray的數據類型。

例如:生成自然序列

import numpy as np

dn = np.arange(1, 10, 1)
print(dn) # [1 2 3 4 5 6 7 8 9]

numpy.linspace()函數用于在指定的數值區間內返回均勻間隔的一維等差數組,默認均分為50份。

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
參數 描述
start 數值區間起始值
stop 數值區間終止值
num 數值區間生成均勻樣本數量,默認50份。
endpoint 生成的數列是否stop終止值
retstep 生成的數列中是否顯示公差項
dtype 生成的數列元素的數據類型

例如:生成1~10之間公差為0.25的等分數列

import numpy as np

dn = np.linspace(1, 10, 5, endpoint=True)
print(dn) # [ 1.    3.25  5.5   7.75 10.  ]

numpy.logspace()函數用于創建等比數列

numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
參數 描述
start 序列起始值
stop 序列終止值
num 數值范圍區間內樣本數量
endpoint 結果數列是否包含終止值
base 對數函數的log底數,默認為10。
dtype 可選,結果數列元素的數據類型。

例如:順序生成以2作為底數,10個等比數列。

import numpy as np

dn = np.logspace(1, 10, num=10, base=2)
print(dn) # [   2.    4.    8.   16.   32.   64.  128.  256.  512. 1024.]

索引切片

若要訪問或修改數組中的元素,可采用索引或切片的方式。默認數組索引從0開始,可使用下標索引依次訪問數組中的元素。類似Python中的list列表。

NumPy提供多種類型的索引方式,常見包括基本切片和高級索引。

基本切片

NumPy內置的slice()函數可用來構造切片對象,實現從原始數組上切割出一個新數組。

numpy.slice(start, stop, step)
參數 描述
start 起始索引
stop 終止索引
step 步長

例如:從0~9的自然序列中獲取4~7的新數組

import numpy as np

a = np.arange(10)
print(a) # [0 1 2 3 4 5 6 7 8 9]

s = slice(4, 8, 1)
r = a[s]
print(r) # [4 5 6 7]

基本切片除了使用slice()函數外,還可以直接使用冒號:來分割切片。

import numpy as np

a = np.arange(10)
print(a) # [0 1 2 3 4 5 6 7 8 9]

r = a[4:8:1]
print(r) # [4 5 6 7]

冒號切片

  • 若僅輸入一個“數字”則返回與索引對應的元素,也就是通過下標索引訪問元素。
  • 所采用“冒號+終止索引”方式則會獲取索引 0 到 終止索引之間的元素,不包括終止索引。
  • 若采用“起始索引+冒號”方式則會返回起始索引到終止索引之間的元素
  • 所采用“起始索引+終止索引”方式則返回返回兩個索引之間的所有元素,不包括終止索引。

例如:

import numpy as np

a = np.arange(10)
print(a) # [0 1 2 3 4 5 6 7 8 9]
print(a[5]) # 5
print(a[6:]) # [6 7 8 9]
print(a[:3]) # [0 1 2]
print(a[4:8]) # [4 5 6 7]

多維數組切片

import numpy as np

a = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])
print(a)
print(a[1]) # [4 5 6]
print(a[2:]) # [[7 8 9]]
print(a[:2]) # [[1 2 3] [4 5 6]]
print(a[1:2]) # [[4 5 6]]

多維數組切片中可使用省略號...,若在行位置使用則返回包含所有行元素,反之則包含所有列元素。

import numpy as np

a = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])
print(a[..., 1]) # [2 5 8]
print(a[1, ...]) # [4 5 6]
print(a[..., 1:])
[[2 3]
 [5 6]
 [8 9]]

高級索引

高級索引會返回數組的副本(深拷貝),切片操作返回的只是數組視圖(淺拷貝)。

整數數組索引

整數數組索引可選擇數組中任意一個元素

import numpy as np

a = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])
print(a[[0,1], [2, 1]]) # [3 5]

行索引[0,1],列索引[2,1],行列組合后得到(0,2)(1,1)(0,2)對應的元素為3, (1,1)對應的元素為5。

廣播機制

若兩個數組的維數不同,則元素到元素的操作是禁止的。NumPy的廣播可將較小的數組廣播到較大數組大小,以便形狀兼容。

NumPy中的廣播機制(Broadcast)旨在解決不同形狀數組之間的算數運算問題,形狀運算的前提是必須保證一致。

例如:

import numpy as np

a = np.array([
    [0, 2],
    [4, 6],
])
b = np.array([
    [1, 3],
    [5, 7]
])
c = a * b
print(c)
[
 [ 0  6]
 [20 42]
]

針對不同形狀的數組進行算術運算,為了保證形狀一致,NumPy設計了一種廣播機制,其核心是對形狀較小的數組,在橫向或縱向上進行一定次數的重復,使其與形狀較大的數組擁有相同的維度。因此,當不同形狀的數組運算時會自動出發廣播機制。

import numpy as np

a = np.array([
    [0, 2],
])
b = np.array([
    [1, 3],
    [5, 7]
])
c = a * b
print(c)
[
 [ 0  6]
 [ 0 14]
]

數組迭代

NumPy提供了一個nditer迭代器對象,配合for循環可實現對數組元素的遍歷。

例如:生成4x5共20個元素數組,使用nditer生成迭代器對象。

import numpy as np

a = np.arange(0, 100, 5)
print(a)

a = a.reshape(4, 5)
print(a)

for i in np.nditer(a):
    print(i)

NumPy數組提供了兩種存儲方式,分別是C-order行優先順序和Fortrant-order列優先順序,nditer迭代器對于特定存儲順序的數組會選擇一種與數組內存布局一致的順序,以提升數據的訪問效率。因此遍歷數組元素時,默認是無需考慮數組的存儲順序的。

例如:遍歷數組的轉置數組

import numpy as np

a = np.arange(0, 100, 5)
print(a)

a = a.reshape(4, 5)
print(a)

b = a.T # 獲取轉置數組
print(b)

for i in np.nditer(b):
    print(i, end=",")

數組與轉置數組遍歷順序是一樣的,也就是說它們在內存中的存儲順序是一樣的。

例如:以C樣式訪問轉置數組的副本

import numpy as np

a = np.arange(0, 100, 5)
a = a.reshape(4, 5)
print(a)
[
 [ 0  5 10 15 20]
 [25 30 35 40 45]
 [50 55 60 65 70]
 [75 80 85 90 95]
]

可通過nditer對象的order參數來指定數組的遍歷順序

for i in np.nditer(a, order="C"):
    print(i, end=",")
0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,
for i in np.nditer(a, order="F"):
    print(i, end=",")
0,25,50,75,5,30,55,80,10,35,60,85,15,40,65,90,20,45,70,95,

nditer對象提供了一個可選參數op_flags讀寫模式,表示能否在遍歷數組時對元素進行修改。

讀寫模式 描述
readonly 只讀模式,遍歷時禁止修改元素。
writeonly 只寫模式,遍歷時允許修改元素。
readwrite 讀寫模式,遍歷時允許修改元素。

例如:

import numpy as np

a = np.arange(0, 100, 5)
a = a.reshape(4, 5)

for i in np.nditer(a, op_flags=["readwrite"]):
    i[...] = 10 * i
    print(i, end=",")
0,50,100,150,200,250,300,350,400,450,500,550,600,650,700,750,800,850,900,950,

nditer對象的構造函數具有一個flags參數,可用于外部循環時使用。

flags 描述
c_index 跟蹤C順序的索引
f_index 跟蹤Fortran順序的索引
multi_index 每次迭代都會跟蹤一種索引類型
external_loop 返回的遍歷結果是具有多個值的一維數組

廣播迭代 - 迭代多個數組

若兩個數組都能夠被廣播,nditer對象可同時對其進行迭代。

例如:數組1的維度是3x4,數組2的維度是1x4,同時迭代后,維度小的可以被廣播到維度大的中。

數組操作

  • 數組變維
  • 數組轉置
  • 修改維度
  • 連接分割
  • 增刪改查

數組變維

變維 描述
numpy.reshape() 不改變數組元素的前提下,修改數組的形狀。
numpy.ndarray.flat 返回一個迭代器,可用for循環遍歷其中每個元素。
numpy.ndarray.flatten() 以一維數組的形式返回一份數組的副本,對副本操作不影響原數組。
numpy.reval() 將多維數組中的元素以一維數組的形式展開,返回數組的視圖。修改會影響原始數組。

例如:numpy.ndarray.flat返回數組迭代器,結合for來遍歷元素。

import numpy as np

a = np.arange(9).reshape(3,3)
for i in a.flat:
    print(i, end=",")

例如:numpy.ndarray.flatten()函數將返回一份數組副本,對副本修改不會影響原始數組。

import numpy as np

a = np.arange(9).reshape(3,3)
b = a.flatten(order = "F")
print(b) # [0 3 6 1 4 7 2 5 8]

例如:numpy.ravel()函數將多維數組中元素以一維數組的形式展開,返回數組視圖,修改視圖將直接影響到原數組。

import numpy as np

a = np.arange(9).reshape(3,3)
b = a.ravel(order = "F")
print(b) # [0 3 6 1 4 7 2 5 8]

數組轉置

轉置 描述
numpy.transpose() 將數組維度對換
numpy.T 將數組維度對換,transpose語法糖。
numpy.rollaxis() 沿指定軸向后滾動至特定位置
numpy.swapaxes() 數組軸對換
numpy.transpose(arr, axes)
參數 描述
arr 待操作的數組
axes 可選,元素或整型數列,按照此參數進行轉置。

例如:將3x4轉置為4x3

import numpy as np

a = np.arange(12).reshape(3,4)
# b = np.transpose(a)
b = a.T
print(a)
print(b)

numpy.rollaxis(arr, axis, start)
參數 描述
arr 傳入的數組
axis 沿著哪條軸向后滾動,其它軸的相對位置不變。
start 默認以0軸開始,可根據數組維度調整值。

numpy.swapaxws(arr, axis1, axis2)
參數 描述
arr 傳入的數組
axis1 待交換的軸1
axis2 待交換的軸2

修改維度

修改維度 描述
numpy.broadcast() 返回數組被廣播后的對象
numpy.broadcast_to() 將數組廣播為新的形式
numpy.expand_dims() 擴展數組的形狀
numpy.squeeze() 從數組的形狀中刪除一維項

numpy.broadcast()的返回值是數組被廣播后的對象,入參為兩個數組。


數組連接

數組連接 描述
numpy.concatenate() 沿指定軸連接相同形狀的多個數組
numpy.stack() 沿著新的軸連接一系列數組
numpy.hstack() 沿水平順序堆疊序列中的數組(列方向)
numpy.vstack() 沿垂直方向堆疊序列中的數組(行方向)
numpy.concatenate((arr1, arr2, ...), axis)
參數 描述
arr1,arr2,... 表示一些列相同類型的數組
axis 沿著該參數指定的軸連接數組,默認為0。
import numpy as np

a = np.array([[1, 2], [3, 4]])
b = np.array([[10, 20], [30, 40]])

默認axis為0表示沿著垂直方向連接,注意數組形狀必須一致。

c = np.concatenate((a,b))
print(c)
[
 [ 1  2]
 [ 3  4]
 [10 20]
 [30 40]
]

當axis為1時表示沿著水平方向連接,注意數組形狀必須一致。

d = np.concatenate((a,b), axis=1)
print(d)
[
 [ 1  2 10 20]
 [ 3  4 30 40]
]

數組分割

函數 描述
ndarray.split() 將一個數組分割為多個子數組
ndarray.hsplit() 將一個數組水平按列分割為多個子數組
ndarray.vsplit() 將一個數組垂直按行分割為多個子數組

ndarray.split()會沿著指定的軸將數組分割為多個子數組

ndarray.split(ary, indices_or_sections, axis)
參數 描述
arr 待分割的數組
indices_or_sections 若為整數表示用該整數平均切分,若為數組則為沿軸切分的位置(左開右閉)。
axis 為0表示橫向切分,為1表示縱向切分。
import numpy as np

a = np.arange(10)
print(a) # [0 1 2 3 4 5 6 7 8 9]

b = np.split(a, 2)
print(b) # [array([0, 1, 2, 3, 4]), array([5, 6, 7, 8, 9])]

c = np.split(a, [3,6])
print(c) # [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8, 9])]

增刪改查

增刪改查 描述
numpy.resize() 獲取指定形狀的新數組
numpy.append() 將元素值添加到數組末尾
numpy.insert() 沿規定軸將元素值插入到指定元素前
numpy.delete() 刪除某個軸上的子數組,同時返回刪除后的新數組。
numpy.argwhere() 獲取數組內符合條件的元素的索引
numpy.unique() 刪除數組中重復元素,并按元素值從大到小排列,返回新數組。

numpy.resize(arr, shape)
  • resize用于獲取指定形狀的新數組

例如:

import numpy as np

a = np.arange(10)
print(a.shape) # (10,)
b = np.resize(a, (2,2))
print(b)
[
 [0 1]
 [2 3]
]

numpy.append(arr, values, axis=None)
  • append用于在數組末尾添加值,同時返回新數組。
參數 描述
arr 輸入數組
values 向輸入數組中添加值,需和arr形狀保持一致。
axis 為None返回一維數組,為0列不變追到行。為1行不變追加到列。
import numpy as np

a = np.arange(6).reshape(2,3)

追加到末尾,返回一維數組。

b = np.append(a, [10])
print(b) # [ 0  1  2  3  4  5 10]

列不變追加到行

b = np.append(a, [[10, 20, 30]], axis = 0)
print(b)
[
 [ 0  1  2]
 [ 3  4  5]
 [10 20 30]
]

行不變追加到列

b = np.append(a, [[10], [20]], axis = 1)
print(b)
[
 [ 0  1  2 10]
 [ 3  4  5 20]
]

numpy.insert(arr, idx, values, axis)
  • insert用于沿著指定的軸,在給定索引值的前一個位置插入值。若未指定軸則輸入數組會被展開為一維數組。
參數 描述
arr 輸入的數組
idx 索引值,在該值之前插入values值。
values 要插入的值
axis 指定的軸,若無則輸入數組會被展開為一維數組。
import numpy as np

a = np.arange(6).reshape(2,3)
b = np.insert(a, 3, [10, 20, 30])
print(b)
[ 0  1  2 10 20 30  3  4  5]

沿著垂直方向插入

b = np.insert(a, 1, [10], axis = 0)
print(b)
[
 [ 0  1  2]
 [10 10 10]
 [ 3  4  5]
]

沿著水平方向插入

b = np.insert(a, 1, [10], axis = 1)
print(b)
[
 [ 0 10  1  2]
 [ 3 10  4  5]
]

  • numpy.delete()函數用于從輸入數組中刪除指定的子數組,并返回一個新數組。
  • numpy.delete()函數與insert()函數相似,若無axis參數則輸入數組會被展開為一維數組。
numpy.delete(arr, obj, axis)
參數 描述
arr 輸入數組
obj 整數或整數數組,表示要被刪除數組元素或子數組。
axis 沿著那條軸刪除子數組

例如:刪除值為1的元素

import numpy as np

a = np.arange(6).reshape(3,2)
b = np.delete(a, 1)
print(b) # [0 2 3 4 5]

沿著橫軸刪除下標為1的一行

b = np.delete(a, 1, axis=0)
print(b)
[
 [0 1]
 [4 5]
]

沿著縱軸刪除下標為1的一列

b = np.delete(a, 1, axis=1)
print(b)
[
 [0]
 [2]
 [4]
]

numpy.argwhere

  • numpy.argwhere()函數返回數組中非0元素的索引
  • 多維數組會返回行列索引組成的索引坐標

例如:

import numpy as np

a = np.arange(6)
b = np.argwhere(a > 1)
print(b)
[
 [2]
 [3]
 [4]
 [5]
]

多維數組返回行列索引坐標

a = np.arange(6).reshape(2,3)
b = np.argwhere(a > 1)
print(b)
[
 [0 2]
 [1 0]
 [1 1]
 [1 2]
]

numpy.unique

  • numpy.unique()函數用于刪除數組中重復的元素
numpy.unique(arr, return_index, return_inverse, return_counts)
參數 描述
arr 輸入數組,多維數組則以一維數組的形式展開。
return_index 返回新數組元素在原數組中的索引位置
return_inverse 返回原數組元素在新數組中的索引位置
return_counts 返回去重后的數組在原數組中出現的次數
import numpy as np

a = np.array([3,2,1,2,1,5])
b = np.unique(a)
print(b) # [1 2 3 5]

返回原數組元素在新數組中的索引位置

b = np.unique(a, return_index=True)
print(b)
(array([1, 2, 3, 5]), array([2, 1, 0, 5], dtype=int64))

返回原數組元素在新數組中的索引位置

b = np.unique(a, return_inverse=True)
print(b)
(array([1, 2, 3, 5]), array([2, 1, 0, 1, 0, 3], dtype=int64))

返回去重后的數組在原數組中出現的次數

b = np.unique(a, return_counts=True)
print(b)
(array([1, 2, 3, 5]), array([2, 2, 1, 1], dtype=int64))

位運算

位運算符 函數 描述
& numpy.bitwise_and() 計算數組之間按位與運算的結果
| numpy.bitwise_or() 計算數組之間按位或運算的結果
~ numpy.invert() 計算元素之間按位取反運算的結果
<< numpy.left_shift() 將二進制數的位數向左移動
>> numpy.right_shift() 將二進制數的位數向右移動

按位與

  • 若兩個二進制數對應位均為1則按位與運算后,該位的結果位1。
  • 若兩個二進制數對應位均為0則按位與運算后,該位的結果位0。
  • 若兩個二進制數對應位均為1或0則按位與運算后,該位的結果位0。
A B AND(A,B)
1 1 1
0 0 0
1 0 0
0 1 0

例如:十進制10和12按位與運算后為十進制的8,即二進制1000。

import numpy as np

a,b = 10,12
print(bin(a), bin(b), np.bitwise_and(a,b)) # 0b1010 0b1100 8
1010 & 1100 = 1000

按位或bitwise_or()

  • 按位或運算后只要對應二進制位上有一個為1,則運算結果為1,否則為0。
    A|B|A|B
    -|-|-
    1|1|1
    0|0|0
    1|0|1
    0|1|1

按位取反invert()

  • 按位取反會對數組中整數按位取反,即0變1,1變0。
  • 有符號的負整數時會取二進制補碼,并執行+1操作。
  • 有符號二進制最高位為0時表示正數,最高位為1時表示負數。

可通過numpy.binary_repr()函數來設置二進制數的位數

import numpy as np

a = np.array([10, 20, 30], dtype=np.uint8)
print(a, np.binary_repr(10)) # [10 20 30] 1010
print(np.invert(a)) # [245 235 225]

按位左移

  • numpy.left_shift()函數會將數組的二進制數向左移動到指定位置,同時返回對應的二進制數。
import numpy as np

print(np.left_shift(1, 2)) # 4

--

按位右移

  • right_shift()函數會將數組中元素的二進制向右移動到指定位置
  • right_shift()函數的返回值對應的是二進制
import numpy as np
print(np.binary_repr(2, width=2))
print(np.right_shift(2, 2))
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容