- NumPy是Numeric Python的简称
- NumPy是Python科学计算的基础工具包
- NumPy是Python数值计算扩展,专门用于处理矩阵,其运算效率比列表更高效。
- NumPy底层使用C编写,能高效地执行数值计算。
随着数据科学(Data Science,DS)发展,科学计算、数据处理等数据分析库大量增长。在矩阵乘法和数组形状处理上,NumPy具有较好的优势。
- 数组算数、逻辑运算
- 傅里叶变换、图形操作
- 线性代数操作
NumPy通常会与SciPy和Matplotlib绘图库组合使用,此组合广泛用于替代MatLab,是一种流行的技术计算平台。
学习资料
- http://c.biancheng.net/numpy/dtype.html
- https://www.runoob.com/numpy/numpy-array-creation.html
安装
查看是否安装
- 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]
即如此。
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]
例如:创建多维数组并转化为复数类型
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_ |
布尔类型,值为True 或False 。 |
int_ |
模型整型,类似C中的long 、int32 、int64 。 |
intc |
类似C中的int 类型,一般为int32 或int64 。 |
intp |
用于索引的整型,类似C中的ssize_t ,一般为int32 或int64 。 |
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', '
数据类型对象
- 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中每个线性的数组称为一个轴Z
axis
,也就是维度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)) #
维数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))