NumPy,全称Numerical Python,是一个开源的Python库,它为Python提供了强大的多维数组对象和用于处理这些数组的函数。NumPy的核心是ndarray,它是一个高效的多维数组容器,用于存储和处理大规模的数据。NumPy还提供了许多数学函数,用于数组之间的操作,以及用于线性代数、傅立叶变换和随机数生成等功能。

基本使用

创建数组

ndarray

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)

上面的构造器接受以下参数:

参数 描述
object 返回一个数组或任何(嵌套)序列
dtype 数组的所需数据类型,可选
copy 可选,默认为true,对象是否被复制
order C(按行)、F(按列)或A(任意,默认)
subok 默认情况下,返回的数组被强制为基类数组。 如果为true,则返回子类
ndmin 指定返回数组的最小维数

示例

import numpy as np 
a = np.array([1,2,3])
b = np.array([[1,2],[3,4]])
c = np.array([1,2,3,4,5], ndmin = 2)
'''
a = [1, 2, 3]
b = [[1, 2] ,[3, 4]]
c = [[1,2,3,4,5]]
'''

empty

创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组

numpy.empty(shape, dtype = float, order = 'C')

zeros

创建指定大小的数组,数组元素以 0 来填充:

numpy.zeros(shape, dtype = float, order = 'C')

ones

创建指定形状的数组,数组元素以 1 来填充:

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

zeros_like

创建一个与给定数组具有相同形状的数组,数组元素以 0 来填充

numpy.zeros_like(a, dtype=None, order='K', subok=True, shape=None)

import numpy as np

# 创建一个 3x3 的二维数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 创建一个与 arr 形状相同的,所有元素都为 0 的数组
zeros_arr = np.zeros_like(arr)
print(zeros_arr)

asarray

类似numpy.array,但参数只有三个

numpy.asarray(a, dtype = None, order = None)

示例

import numpy as np 

x = [1,2,3]
a = np.asarray(x) # [1,2,3]

x = (1,2,3)
a = np.asarray(x) # [1,2,3]

x = [(1,2,3),(4,5)]
a = np.asarray(x) # [1,2,3]

arange

创建数值范围并返回ndarray对象

numpy.arange(start, stop, step, dtype)

参数 描述
start 起始值,默认为0
stop 终止值(不包含)
step 步长,默认为1
dtype 返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型。

示例

import numpy as np
x = np.arange(10,20,2)
print(x) # [10 12 14 16 18]

linspace

用于创建一个一维数组,数组是一个等差数列构成的

np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

参数 描述
start 序列的起始值
stop 序列的终止值,如果endpointtrue,该值包含于数列中
num 要生成的等步长的样本数量,默认为50
endpoint 该值为true时,数列中包含stop值,反之不包含,默认是True
retstep 如果为true时,生成的数组中会显示间距,反之不显示
dtype 数据类型

示例

import numpy as np
# 设置起始点为 1 ,终止点为 10,数列个数为 10
a = np.linspace(1,10,10)
print(a) # [ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]

a = np.linspace(10, 20, 5, endpoint = False)
print(a) # [10. 12. 14. 16. 18.]

logspace

用于创建一个等比数列

np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)

参数 描述
start 序列的起始值为:$base^{start}$
stop 序列的终止值为:$base^{stop}$。如果endpointtrue,该值包含于数列中
num 要生成的等步长的样本数量,默认为50
endpoint 该值为 true 时,数列中中包含stop值,反之不包含,默认是true
base 对数 log 的底数,默认底数是 10
dtype 数据类型

示例

import numpy as np
# 默认底数是 10
a = np.logspace(1.0, 2.0, num = 10)
print (a) # [ 10. 12.91549665 16.68100537 21.5443469 27.82559402 35.93813664 46.41588834 59.94842503 77.42636827 100.]

# 对数的底数设置为 2
a = np.logspace(0,9,10,base=2)
print (a) # [ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]

数据类型

NumPy支持比Python更多种类的数值类型

数据类型 描述
bool_ 存储为一个字节的布尔值(真或假)
int_ 默认整数,相当于 C 的long,通常为int32int64
intc 相当于 C 的int,通常为int32int64
intp 用于索引的整数,相当于 C 的size_t,通常为int32int64
int8 字节(-128 ~ 127)
int16 16 位整数(-32768 ~ 32767)
int32 32 位整数(-2147483648 ~ 2147483647)
int64 64 位整数(-9223372036854775808 ~ 9223372036854775807)
uint8 8 位无符号整数(0 ~ 255)
uint16 16 位无符号整数(0 ~ 65535)
uint32 32 位无符号整数(0 ~ 4294967295)
uint64 64 位无符号整数(0 ~ 18446744073709551615)
float_ float64的简写
float16 半精度浮点:符号位,5 位指数,10 位尾数
float32 单精度浮点:符号位,8 位指数,23 位尾数
float64 双精度浮点:符号位,11 位指数,52 位尾数
complex_ complex128的简写
complex64 复数,由两个 32 位浮点表示(实部和虚部)
complex128 复数,由两个 64 位浮点表示(实部和虚部)

NumPy数字类型是dtype(数据类型)对象的实例,每个对象具有唯一的特征。这些类型可以是np.bool_np.float32等。

数据类型对象描述了对应于数组的固定内存块的解释,取决于以下方面:

  • 数据类型(整数、浮点或者Python对象)
  • 数据大小
  • 字节序(小端或大端)
  • 在结构化类型的情况下,字段的名称,每个字段的数据类型,和每个字段占用的内存块部分
  • 如果数据类型是子序列,它的形状和数据类型

字节顺序取决于数据类型的前缀<><意味着编码是小端(最小有效字节存储在最小地址中)。 >意味着编码是大端(最大有效字节存储在最小地址中)。

dtype可由以下语法构造:

numpy.dtype(object, align, copy)
  • Object:被转换为数据类型的对象
  • align:向字段添加间隔,填充字段使其类似结构体
  • copy:生成dtype对象的新副本,如果为false,结果是内建数据类型对象的引用

示例

import numpy as np
# 使用标量类型
dt = np.dtype(np.int32)
# int8, int16, int32, int64 四种数据类型可以使用字符串 'i1', 'i2','i4','i8' 代替
dt = np.dtype('i4')
# 将数据类型应用于 ndarray 对象
dt = np.dtype([('age',np.int8)])
a = np.array([(10,),(20,),(30,)], dtype = dt)

student = np.dtype([('name','S20'), ('age', 'i1'), ('marks', 'f4')])
a = np.array([('abc', 21, 50),('xyz', 18, 75)], dtype = student)
# [('abc', 21, 50.0), ('xyz', 18, 75.0)]

数组属性

数组的维数称为秩(rank),秩就是轴的数量,一维数组的秩为1,二维数组的秩为2

在NumPy中,每一个线性的数组称为是一个轴(axis),也就是维度(dimensions)。比如说,二维数组相当于是两个一维数组,其中第一个一维数组中每个元素又是一个一维数组。所以一维数组就是NumPy中的轴,第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量秩,就是数组的维数。

很多时候可以声明axis。axis=0,表示沿着第0轴进行操作,即对每一列进行操作;axis=1,表示沿着第1轴进行操作,即对每一行进行操作

NumPy的数组中比较重要ndarray对象属性有:

属性 说明
ndarray.ndim 秩,即轴的数量或维度的数量
ndarray.shape 数组的维度,对于矩阵,n行m列
ndarray.size 数组元素的总个数,相当于.shape中n*m的值
ndarray.dtype 元素类型
ndarray.itemsize 每个元素的大小,以字节为单位
ndarray.flags 内存信息
ndarray.real 实部
ndarray.imag 虚部

示例

import numpy as np 

a = np.arange(24)
print (a.ndim) # 1

# 调整大小
b = a.reshape(2,4,3)
print (b.ndim) # 2

a = np.array([[1,2,3],[4,5,6]])
print (a.shape) # (2, 3)
# 调整数组大小
a.shape = (3,2)
print (a) # [[1 2],[3 4],[5 6]]

切片和索引

ndarray对象的内容可以通过索引或切片来访问和修改,与Python中list的切片操作一样。

ndarray数组可以基于0-n的下标进行索引,切片对象可以通过内置的slice函数,并设置start, stop及step参数进行,从原数组中切割出一个新数组

import numpy as np

a = np.arange(10)
s = slice(2,7,2) # 从索引 2 开始到索引 7 停止,间隔为2
print (a[s]) # [2 4 6]

b = a[2:7:2] # 从索引 2 开始到索引 7 停止,间隔为 2
print(b) # [2 4 6]

多维数组同样适用上述索引提取方法:

import numpy as np

a = np.array([[1,2,3],[3,4,5],[4,5,6]])
print(a)
# 从某个索引处开始切割
print('从数组索引 a[1:] 处开始切割')
print(a[1:])
'''
[[1 2 3]
[3 4 5]
[4 5 6]]
从数组索引 a[1:] 处开始切割
[[3 4 5]
[4 5 6]]
'''

切片还可以包括省略号**…**,如果在行位置使用省略号,它将返回包含行中元素的 ndarray。

import numpy as np

a = np.array([[1,2,3],[3,4,5],[4,5,6]])
print (a[...,1]) # 第2列元素
print (a[1,...]) # 第2行元素
print (a[...,1:]) # 第2列及剩下的所有元素
  • a[..., 1] 的意思是:选择数组 a 的所有行,并选取每行的第2个元素(索引1处的元素)
  • a[1, ...] 的意思是:选取数组 a 的第2行(索引1处的整行),并保留该行的所有列
  • ... 表示取所有剩余维度

高级索引

整数数组索引

整数数组索引是指使用一个数组来访问另一个数组的元素。这个数组中的每个元素都是目标数组中某个维度上的索引值。

import numpy as np 

x = np.array([[1, 2], [3, 4], [5, 6]])
# 获取数组中 (0,0)、(1,1)和(2,0)位置处的元素
y = x[[0,1,2], [0,1,0]]
print (y)

x[[0, 1, 2], [0, 1, 0]]的意思是:

  • 选取x中的元素,其行索引由第一个数组 [0, 1, 2] 指定
  • 列索引由第二个数组 [0, 1, 0] 指定

具体选取的元素为:

  • x[0, 0] -> 第0行第0列的元素,值为1
  • x[1, 1] -> 第1行第1列的元素,值为4
  • x[2, 0] -> 第2行第0列的元素,值为5

布尔索引

可以通过一个布尔数组来索引目标数组,布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组

import numpy as np 

x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
print (x)
# 打印出大于5的元素
print ('大于 5 的元素是:')
print (x[x > 5])
'''
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
大于 5 的元素是:
[ 6 7 8 9 10 11]
'''

广播

广播(Broadcast)是numpy对不同形状(shape)的数组(a.shape != b.shape)进行数值计算的方式,对数组的算术运算通常在相应的元素上进行。

import numpy as np 

a = np.array([[ 0, 0, 0],
[10,10,10],
[20,20,20],
[30,30,30]])
b = np.array([0,1,2])
print(a + b)
'''
[[ 0 1 2]
[10 11 12]
[20 21 22]
[30 31 32]]
'''

3x3的二维数组与长为3的一维数组相加,等效于把一维数组在二维上重复3次再运算

广播规则

  • 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加1补齐
  • 输出数组的形状是输入数组形状的各个维度上的最大值
  • 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为1时,这个数组能够用来计算,否则出错
  • 当输入数组的某个维度的长度为1时,沿着此维度运算时都用此维度上的第一组值

简单理解:

对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:

  • 数组拥有相同形状
  • 当前维度的值相等
  • 当前维度的值有一个是 1

若条件不满足,抛出 “ValueError: frames are not aligned” 异常

统计函数

NumPy提供了很多统计函数,用于从数组中查找最小元素,最大元素,百分位标准差和方差等

numpy.amin() 和 numpy.amax()

用于计算数组中的元素沿指定轴的最小值

numpy.(amin|amax)(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)

  • a: 输入的数组,可以是一个NumPy数组或类似数组的对象
  • axis: 可选参数,用于指定在哪个轴上计算最值。如果不提供此参数,则返回整个数组的最小值。可以是一个整数表示轴的索引,也可以是一个元组表示多个轴
  • out: 可选参数,用于指定结果的存储位置
  • keepdims: 可选参数,如果为True,将保持结果数组的维度数目与输入数组相同。如果为False(默认值),则会去除计算后维度为1的轴
  • initial: 可选参数,用于指定一个初始值,然后在数组的元素上计算最值
  • where: 可选参数,一个布尔数组,用于指定仅考虑满足条件的元素

numpy.ptp()

计算数组中元素最大值与最小值的差(最大值 - 最小值)。

numpy.ptp(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)

  • axis: 可选参数,用于指定在哪个轴上计算峰值。如果不提供此参数,则返回整个数组的峰值。可以是一个整数表示轴的索引,也可以是一个元组表示多个轴
  • initial: 可选参数,用于指定一个初始值,然后在数组的元素上计算峰值

numpy.percentile()

百分位数是统计中使用的度量,表示小于这个值的观察值的百分比

numpy.percentile(a, q, axis)

  • a: 输入数组
  • q: 要计算的百分位数,在0~100之间
  • axis: 沿着它计算百分位数的轴

百分位数:

第p个百分位数是这样一个值,它使得至少有p%的数据项小于或等于这个值,且至少有(100-p)%的数据项大于或等于这个值

numpy.median()

用于计算数组a中元素的中位数(中值)

numpy.median(a, axis=None, out=None, overwrite_input=False, keepdims=<no value>)

import numpy as np 

a = np.arange(6).reshape(3,2)
print ('我们的数组是:')
print (a)
print ('\n')
print ('修改后的数组:')
wt = np.array([3,5])
print (np.average(a, axis = 1, weights = wt))
print ('\n')
print ('修改后的数组:')
print (np.average(a, axis = 1, weights = wt, returned = True))

numpy.mean()

返回数组中元素的平均值,如果提供了轴,则沿其计算,算术平均值是沿轴的元素的总和除以元素的数量

numpy.mean(a, axis=None, dtype=None, out=None, keepdims=<no value>)

numpy.average()

根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值,该函数可以接受一个轴参数。如果没有指定轴,则数组会被展开

numpy.average(a, axis=None, weights=None, returned=False)

加权平均值即将各数值乘以相应的权数,然后加总求和得到总体值,再除以总的单位数

考虑数组[1,2,3,4]和相应的权重[4,3,2,1],通过将相应元素的乘积相加,并将和除以权重的和,来计算加权平均值

加权平均值 = (1*4+2*3+3*2+4*1)/(4+3+2+1)

方差

统计中的方差(样本方差)是每个样本值与全体样本值的平均数之差的平方的平均数

numpy.var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=<no value>, *, where=<no value>, mean=<no value>)

标准差

标准差是一组数据平均值分散程度的一种度量。标准差是方差的算术平方根。

numpy.std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False)

数学函数

三角函数

NumPy 提供了标准的三角函数:sin()、cos()、tan()

import numpy as np

a = np.array([0,30,45,60,90])
print('含有正弦值的数组:')
sin = np.sin(a*np.pi/180)
print(sin)
print('计算角度的反正弦,返回值以弧度为单位:')
inv = np.arcsin(sin)
print(inv)
print('通过转化为角度制来检查结果:')
print(np.degrees(inv))
print('arccos 和 arctan 函数行为类似:')
cos = np.cos(a*np.pi/180)
print(cos)
print('反余弦:')
inv = np.arccos(cos)
print(inv)
print('角度制单位:')
print(np.degrees(inv))
print('tan 函数:')
tan = np.tan(a*np.pi/180)
print(tan)
print('反正切:')
inv = np.arctan(tan)
print(inv)
print('角度制单位:')
print(np.degrees(inv))

舍入函数

返回指定数字的四舍五入值

numpy.around(a,decimals)

  • a: 数组
  • decimals: 舍入的小数位数。 默认值为0。 如果为负,整数将四舍五入到小数点左侧的位置
import numpy as np

a = np.array([1.0,5.55, 123, 0.567, 25.532])
print ('原数组:')
print (a)
print ('\n')
print ('舍入后:')
print (np.around(a))
print (np.around(a, decimals = 1))
print (np.around(a, decimals = -1))
'''
原数组:
[ 1. 5.55 123. 0.567 25.532]

舍入后:
[ 1. 6. 123. 1. 26.]
[ 1. 5.6 123. 0.6 25.5]
[ 0. 10. 120. 0. 30.]
'''

矩阵库

NumPy 中包含了一个矩阵库 numpy.matlib,该模块中的函数返回的是一个矩阵,而不是 ndarray 对象

一个m*n的矩阵是一个由m行n列元素排列成的矩形阵列,矩阵里的元素可以是数字、符号或数学式。

import numpy as np

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

print ('原数组:')
print (a)
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]]
'''

matlib.empty()

返回一个新的矩阵,矩阵内的元素为未初始化的值:

numpy.matlib.empty(shape, dtype, order)

  • shape: 定义新矩阵形状的整数或整数元组
  • Dtype: 可选,数据类型
  • order: C(行序优先) 或者 F(列序优先)

matlib.zeros()

创建一个以 0 填充的矩阵

matlib.ones()

创建一个以 1 填充的矩阵

matlib.eye()

返回一个矩阵,对角线元素为1,其他位置为零

numpy.matlib.eye(n, M,k, dtype)

  • n: 返回矩阵的行数
  • M: 返回矩阵的列数,默认为 n
  • k: 对角线的索引
  • dtype: 数据类型

matlib.identity()

返回给定大小的单位矩阵

matlib.rand()

创建一个给定大小的矩阵,数据是随机填充的

numpy线性代数

NumPy 提供了线性代数函数库 linalg,该库包含了线性代数所需的所有功能

函数 描述
dot 两个数组的点积,即元素对应相乘。
vdot 两个向量的点积
inner 两个数组的内积
matmul 两个数组的矩阵积
determinant 数组的行列式
solve 求解线性矩阵方程
inv 计算矩阵的乘法逆矩阵

numpy.dot()

对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为向量点积);

对于二维数组,计算的是两个数组的矩阵乘积;

对于多维数组,它的通用计算公式如下,即结果数组中的每个元素都是数组a的最后一维上的所有元素与数组b的倒数第二维上的所有元素的乘积和:dot(a, b)[i,j,k,m] = sum(a[i,j,:] \* b[k,:,m])

numpy.dot(a, b, out=None)

  • a:ndarray 数组
  • b:ndarray 数组
  • out:ndarray, 可选,用来保存dot()的计算结果

numpy.vdot()

计算两个向量的点积。 如果第一个参数是复数,那么它的共轭复数会用于计算。 如果参数是多维数组,它会被展开。

import numpy as np 

a = np.array([[1,2],[3,4]])
b = np.array([[11,12],[13,14]])

# vdot 将数组展开计算内积
print (np.vdot(a,b))
# 1*11 + 2*12 + 3*13 + 4*14 = 130

numpy.inner()

numpy.inner() 函数返回一维数组的向量内积。对于更高的维度,它返回最后一个轴上的和的乘积。

numpy.matmul

返回两个数组的矩阵乘积。

虽然它返回二维数组的正常乘积,但如果任一参数的维数大于2,则将其视为存在于最后两个索引的矩阵的栈,并进行相应广播。

另一方面,如果任一参数是一维数组,则通过在其维度上附加 1 来将其提升为矩阵,并在乘法之后被去除。

对于二维数组,它就是矩阵乘法

numpy.linalg.det()

计算输入矩阵的行列式

numpy.linalg.solve()

矩阵形式的线性方程的解。

考虑以下线性方程:

x + y + z = 6

2y + 5z = -4

2x + 5y - z = 27

可以使用矩阵表示为:

1  1  1   x      6
0 2 5 y = -4
2 5 -1 z 27

如果矩阵成为A、X和B,方程变为:AX = BX = A^(-1)B

numpy.linalg.inv()

计算矩阵的逆矩阵。

逆矩阵(inverse matrix):设A是数域上的一个n阶矩阵,若在相同数域上存在另一个n阶矩阵B,使得:AB=BA=E,则我们称B是A的逆矩阵,而A则被称为可逆矩阵