1.导论及背景
官网: https://numpy.org/
这里的文档: NumPy 文档 — NumPy v1.26 手册 包括,新手指南, 用户手册,Numpy API绝对是学习Numpy的好东西
NumPy 源代码:https://github.com/numpy/numpy
1.1什么是numpy
NumPy(Numerical Python的缩写)是Python中用于科学计算、数据分析和机器学习的底层库,补充了Python语言所欠缺的数值计算能力。
NumPy在各种科学和工程领域中都得到了广泛的应用,包括但不限于:
-
数据分析和处理:NumPy用于处理大量的数值数据,执行数据清洗、转换、汇总等操作。
-
信号处理:音频、图像处理领域广泛使用NumPy来处理信号和图像数据。
-
机器学习:NumPy数组通常用于存储和处理机器学习算法中的输入数据和模型参数。
-
模拟和建模:科学家和工程师使用NumPy来模拟现象、进行实验和构建数值模型。
1.2 Python原生列表 vs. NumPy数组
虽然Python原生列表在处理小规模数据时是方便的,但是当涉及大规模数据处理和复杂的数值计算时,NumPy数组的优势显而易见:
- 性能:NumPy数组经过优化,可以比Python原生列表更快地进行数值运算,这对于大型数据集和复杂计算至关重要。
- 内存占用:NumPy数组更紧凑地存储数据,占用更少的内存空间,有助于处理大量数据。
- 便利性:NumPy提供了丰富的数组操作函数,使得编写简洁且高效的代码更加容易。
- 向量化操作:NumPy鼓励使用向量化操作,避免了在Python原生列表中使用循环的低效情况。
- 提供大量的数学函数库
1.3 环境搭建
pip install numpy
2.编写 NumPy 程序
NumPy 库中最重要的数据结构是多维数组对象(ndarray),它是一系列同类型数据的集合,下标索引从 0 开始。
ndarray 对象是用于存放同类型元素的多维数组。
ndarray 中的每个元素在内存中都有相同存储大小的区域。
2.1 创建一维数组
import numpy as np
a = np.array([1, 2, 3])
print(a)
print(type(a))
array 函数创建 ndarray 对象,其中参数可以是如下类型:
- 列表
- 元组
import numpy as np
a = np.array((1, 2, 3))
print(a)
ndarray和列表的主要区别:ndarray只能保存相同类型的数据,而列表中可以存储不同类型的数据。
数组转列表:a.tolist()
2.2 NumPy 数据类型
2.2.1 numpy支持的数据类型
在官网 NumPy 基础知识 — NumPy v1.26 手册 中,有如下列描述:
NumPy可以使用字类型编码来表述数据类型,这是为了兼容NumPy的前身Numeric,不建议使用 。
能看出其支持的类型比python要多,而且是和C语言的数据类型相对应的。
import numpy as np
b = np.array([1., 2., 3.])
print(b)
print(b.dtype)#float64
dtype返回的是数组元素的类型。
也可以在定义数组时指定数据类型。
import numpy as np
b = np.array((1, 2, 3, 4), dtype=np.float16)
print(b)
print(b.dtype)
import numpy as np
d = np.array([1+2j, 3+4j, 5+6*1j], dtype=np.csingle)
print(d.dtype) #complex64
e = np.array([True, False, False, True])
print(e.dtype)
f = np.array(['您好', 'Hello', 'Halloaa'])
print(f.dtype) # <U7 (小端格式 unicode 7)
2.2.2 类型转换
使用数组对象(ndarray)的 astype(dtype)方法可以转换数组元素的数据类型。
import numpy as np
a = np.array([1.0, 2.1, 3.9])
print(a)
print(a.dtype)
b = a.astype(np.int32)
print(b)
print(b.dtype)
b[0]=10
注意: astype(dtype)方法会创建一个新的对象
import numpy as np
c = np.array(["1.0", "-2.1", "3.9"])
print(c)
print(c.dtype)
d = c.astype("f4")
print(d)
print(d.dtype)
注意:如果类型不兼容则会抛出TypeError错误。
2.2 创建一维数组的其它方式
使用 array()函数是将 Python 内置的列表或元组转换为 NumPy 数组对象, 这样做效率不高。为此 NumPy 提供了很多创建数组的函数。
2.2.1 使用 arange 函数
NumPy 包中的使用 arange 函数创建数值范围并返回数组对象,与 Python 中类型是 range 函数类似。arange 函数语法格式如下:
#start 是开始值,可以省略,默认值为 0,包含开始值
#stop 是结束值,不包含结束值。(左闭右开)
#step 是步长,默认值为 1。
#dtype 是数组元素类型。
numpy.arange([start, ]stop, [step, ] dtype=None)
注意: 步长step可以为负数,可以创建递减序列。
import numpy as np
a = np.arange(10)
print(a)
b = np.arange(1, 10, 2)
print(b)
c = np.arange(1, -10, -3)
print(c)
d = np.arange(1, -10, -1 , dtype='f8')
print(d)
print(d.dtype)
2.2.2 等差数列与 linspace 函数
linspace(线性等分向量)函数创建等差数列,语法格式如下:
'''
start 是开始值,包含开始值。
stop 是结束值,默认包含结束值。
num 是设置生成的元素个数。
endpoint 是否包含结束值(stop),False 是不包含,True 是包含,默认值是 True。
retstep 是否返回步长(或公差),False 是不返回,默认值是 False。True是返回,当为 True 是返回值是二元组(数列数组,步长)。
'''
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
import numpy as np
a = np.linspace(0, 10, 10)
print(a)
b = np.linspace(0, 10, 10, endpoint=False)
print(b)
c = np.linspace(0, 10, 10,endpoint=False, retstep=True)
print(c)
mystep = c[1]
print("步长=", mystep)
2.2.3 等比数列与 logspace 函数(了解)
logspace(对数等分向量)函数创建等比数列,语法格式如下:
"""
start 是开始值 base ** start。
stop 是结束值 base ** stop。
base 是底数。
"""
numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
import numpy as np
a = np.logspace(0, 9, 10)
print(a)
b = np.logspace(0, 10, 10, endpoint=False)
print(b)
c = np.logspace(0, 9, 10, base=2)
print(c)
练习:
-
编写一个 NumPy 程序来创建一个从 30 到 50 的所有偶数整数的数组,取值[30, 50)
import numpy as np array=np.arange(30,50,2) print(array)
-
编写 NumPy 程序以获取有关 np.add 函数的帮助信息
print(np.info(np.add))
-
从给定数组中提取所有偶数
import numpy as np a = np.linspace(1,10,10) print(a[a%2==0]) #可以暂时跳过
-
编写 NumPy 程序创建 20 元素的等比数列数组,指数介于 2 到 5,包括 5。
import numpy as np x = np.logspace(2, 5, 20) print(x)
3.二维数组
3.1 创建二维数组
import numpy as np
L = [[1,2,3], [4,5,6], [7,8,9]]
a = np.array(L) # 嵌套列表创建ndarray数组
print(a)
print(a.dtype)
T1 = ([1.5,2,3], [4,5,6], [7,8,9])
b = np.array(T1) # 嵌套元组创建ndarray数组
print(b)
print(b.dtype)
T2 = ((1,2,3), (4,5,6), (7,8,9))
c = np.array(T2, dtype='f8') # 嵌套元组创建ndarray数组
print(c)
print(c.dtype)
3.2 内存中的数组对象
-
元数据
存储对目标数组的描述信息,如:ndim、shape、dtype、data等。
可以通过执行以下程序,查看ndarray属性信息
import numpy as np L = [[1,2,3], [4,5,6], [7,8,9]] a = np.array(L) help(a)
其中一些常用属性如下表所示。
import numpy as np c = np.array([[1, 2], [3, 4],[5,6]], dtype=complex) print(c) print(c.ndim)#2 print(c.shape)#(3,2) print(c.size)#6 print(c.dtype)#complex128 print(c.itemsize)#16 print(c.real) print(c.imag)
-
二维数组的轴
a2 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(a2)
-
三维数组的轴
a3 = np.array([[[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[20, 21, 22], [23, 24, 25], [26, 27, 28]], [[30, 31, 32], [33, 34, 35], [36, 37, 38]]]) print(a3)
-
-
实际数据
完整的数组数据
将实际数据与元数据分开存放,一方面提高了内存空间的使用效率,另一方面减少对实际数据的访问频率,提高性能。
3.3 重新设置维度
数组的 shape 属性是数组的形状,返回值是一个元组。数组的 reshape() 方法可以重新设置数组的形状。
import numpy as np
d = np.arange(1, 10)
print(d)
print("d的形状:", d.shape)
dd = d.reshape((3, 3)) # 从一维到二维
print(dd)
print("dd的形状:", dd.shape)
print(d)
d.shape = (3,3)
print(d)
3.4 更多创建二维数组方式
arange、linspace 和 logspace 函数都是创建一维数组。还有创建多维数组函数。
3.4.1 ones 函数
ones 函数可以根据指定的形状和数据类型生成全为 1 的数组。语法格式如下:
numpy.ones(shape, dtype=None)
import numpy as np
a = np.ones((2, 3))
print(a)
print(a.dtype)
b = np.ones((2, 3), dtype='i4')
print(b)
print(b.dtype)
c = np.ones((3,)) # 生成一维数组
print(c)
print(c.dtype)
d = np.ones((3, 1)) # 生成列向量数组
print(d)
print(d.dtype)
3.4.2 zeros 函数
zeros 函数可以根据指定的形状和数据类型生成全为 0 的数组。语法格式如下:
numpy.zeros(shape, dtype=float)
import numpy as np
a = np.zeros((2, 3))
print(a)
print(a.dtype)
b = np.zeros((2, 3), dtype='i4')
print(b)
print(b.dtype)
c = np.zeros((3,)) # 生成一维数组
print(c)
print(c.dtype)
d = np.zeros((3, 1)) # 生成列向量数组
print(d)
print(d.dtype)
3.4.3 empty 函数
empty 函数可以根据指定的形状和数据类型生成数组,其中 存放的元素没有初始化。 语法格式如下:
numpy.empty(shape, dtype=float)
import numpy as np
e = np.empty([2, 2])
print(e)
print(e.dtype)
f = np.empty((2, 2), dtype='i4')
print(f)
print(f.dtype)
3.4.4 full 函数
full 函数可以根据指定的形状和数据类型生成数组,并用指定数填充。 语法格式如下:
numpy.full(shape, fill_value, dtype=None)
import numpy as np
a = np.full((2, 4), 10)
print(a)
print(a.dtype)
b = np.full((2, 4), 10, dtype=float)
print(b)
print(b.dtype)
c = np.full(5, 10)
print(c)
print(c.dtype)
3.4.5 eye 函数
eye 函数可以创建二维数组,对角线元素为 1.0,其他元素为 0.0。语法格式如下:
'''
N 是行数。
M 是列数,如果省略,则生成 N x N 矩阵。
k 是对角线开始位置的索引,默认为 0,主对角线。
dtype 指定元素数据类型,默认是 float。
'''
numpy.eye(N, M=None, k=0, dtype=float)
import numpy as np
a = np.eye(3)
print(a)
print(a.dtype)
b = np.eye(6, dtype=np.int_)
print(b)
print(b.dtype)
3.5 数组的转置
数组的 T 属性可以转置数组,将数组轴的索引倒置。
即数组形状为(n, m),转置后的形状为(m, n)。
import numpy as np
a = np.array([[1, 2, 3],
[4, 5, 6]])
print(a, a.shape)
at = a.T
print(at, at.shape)
b = np.array([1, 2, 3, 4])
print(b)
print(b.T) #一维数组不能转置
c = np.array([[1, 2, 3, 4]])
print(c)
print(c.T)
练习:
-
编写 NumPy 程序将给定数组转换为列表
import numpy as np a = [[1, 2], [3, 4]] x = np.array(a) a2 = x.tolist() print(a is a2) print(a == a2)
-
编写一个 NumPy 程序来创建一个空数组
import numpy as np x = np.empty((3,4)) print(x)
-
编写一个 NumPy 程序来创建一个数组,并使用 full 函数填充
import numpy as np y = np.full((3,3),6) print(y)
-
编写一个 NumPy 程序来创建一个大小为 2 x 3 的二维数组,并打印数组、数组形状和类型。
import numpy as np x = np.array([[2, 4, 6], [6, 8, 10]], np.int32) print(type(x)) print(x.shape) print(x.dtype)
-
编写 NumPy 程序,为数组创建新形状
import numpy as np x = np.array([1, 2, 3, 4, 5, 6]) y = np.reshape(x,(3,2)) print("Reshape 3x2:") print(y) z = np.reshape(x,(2,3)) print("Reshape 2x3:") print(z)
4.访问数组
4.1 索引访问
4.1.1 一维数组索引访问
NumPy 一维数组索引访问与 Python 内置序列类型索引访问一样,使用中括号+下标([index])。
import numpy as np
a = np.array([1, 2, 3, 4, 5, 6])
print(a[5])
print(a[-1])
print(a[-1:-4:-1])
4.1.2 二数组维索引访问
多维数组索引访问有两种表达式:
- 表达式1:np.array[0轴索引][1轴索引]…[n-1轴索引]
- 表达式2:np.array[0 轴索引, 1轴索引,…, n-1轴索 引]
import numpy as np
b = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
print(b[2][1])
print(b[2, 1])
print(b[-1][-2])
print(b[-1, -2])
4.2 切片访问
4.2.1 一维数组切片访问
NumPy 一维数组切片操作与 Python 内置序列切片操作一样。语法格式如下:
arr[[start:end:step]]
import numpy as np
a = np.array([1, 2, 3, 4, 5, 6])
print(a[1:-1])
print(a[0:3:2])
print(a[::-1])
4.2.2 二维数组切片访问
多维数组,切片访问语法格式如下所示
np.array[所在 0 轴切片, 所在 1 轴切片,..., 所在 n-1 轴切片]
import numpy as np
b = np.linspace(1,9,9,dtype="i4")
b.shape=(3,3)
print(b)
print(b[1:, 1:3])
注意:如果写成如下形式含义就不同了
np.array[切片][切片]...[切片] # 这种形式都是对0轴的切片
import numpy as np
b = np.linspace(1,9,9,dtype="i4")
b.shape=(3,3)
print(b)
print(b[1:, 1:3])
print('*'*20)
print(b[1:])
print('-'*20)
print(b[1:][1:3])
多维数组切片与索引的访问表达式:
np.array[所在 0 轴切片或索引, 所在 1 轴切片或索引,..., 所在 n-1 轴切片或索引]
import numpy as np
b = np.linspace(1,9,9,dtype="i4")
b.shape=(3,3)
print(b)
print(b[1:,1])
4.3布尔索引
为了从数组中过滤我们想要的元素,可以使用布尔索引。
import numpy as np
a1 = np.array([1, 2, 3, 4, 5, 6])
b = np.array([False, True, False, True, False, True])
print(a1[b])
import numpy as np
a2 = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
#创建与a2相同形状的布尔数组b
b = np.array([[True, False, False],
[False, True, False],
[False, False, True]])
print(a2[b])
#布尔值来源于 a2>3
print(a2[a2>3])
注意:
- 布尔数组必须与要索引的数组形状相同,否则引发IndexError错误
- 布尔索引返回的新数组是原数组的副本,与原数组不共享相同的数据空间。新数组的修改不会影响原数组。这是所谓的深层复制。
import numpy as np
# 创建一维数组
a3 = np.array([1, 2, 3])
# 创建一维布尔数组b
b = np.array([False,True,True])
c = a3[b]
print(c)
c[1] = 100
print(c)
print(a3)
4.4 花式索引
使用整数列表或整数数组作为数组索引,这称为“花式索引”。
4.4.1 一维数组花式索引
原始数组是一维数组,索引数组可以是一维或多维的。
import numpy as np
a = np.array([1, 2, 3, 4, 5, 6])
i = np.array([1, 1, 3, 4])
print(a[i]) #[2 2 4 5]
L = [1, 1, 3, 4]
print(a[L]) #[2 2 4 5]
索引可以是整数数组或整数列表。
import numpy as np
a = np.array([1, 2, 3, 4, 5, 6])
j = np.array([[1, 1],
[3, 4]])
#输出数组形状与索引数组形状相同
print(a[j])
花式索引返回的新数组与布尔数组类似,属于深层复制。
4.4.2 二维数组花式索引
原始数组是多维数组,索引数组可以是一维或多维的。
import numpy as np
b = np.arange(12).reshape(3, 4)
print(b)
# 创建二维索引数组m,作为b数组的0轴索引
m = np.array([[1, 1],
[2, 0]])
# 创建二维索引数组n,作为b数组的1轴索引
n = np.array([[1, 0],
[3, 2]])
print(b[m,n])
可以混合使用整数索引和数组索引。
import numpy as np
b = np.arange(12).reshape(3, 4)
print(b)
# 创建二维索引数组m,作为b数组的0轴索引
m = np.array([[1, 1],
[2, 0]])
# 创建二维索引数组n,作为b数组的1轴索引
n = np.array([[1, 0],
[3, 2]])
print(b[m,n])
# 0轴索引使用二维数组m,1轴索引使用整数
print(b[m, 2])
# 0轴索引使用整数,1轴索引使用二维数组n
print(b[1, n])
4.5 迭代数组
通过数组的 nditer 类可以进行迭代。
import numpy as np
# 创建二维数组
a = np.arange(0,12).reshape(3,4)
print('原始数组是:')
print(a)
print ('迭代输出元素:')
for n in np.nditer(a):
print(n, end=", ")
练习:
-
编写一个 NumPy 程序来创建一个 10x10 矩阵,其中边界上的元素是 1, 内部元素是 0。
import numpy as np x = np.ones((10, 10)) x[1:-1, 1:-1] = 0 print(x)
-
编写一个 NumPy 程序来创建一个 4x4 矩阵,其中 0 和 1 交错,主对角线都是 0。
import numpy as np x = np.zeros((4, 4)) x[::2, 1::2] = 1 x[1::2, ::2] = 1 print(x)
-
编写一个 NumPy 程序来反转一个一维数组(第一个元素成为最后一个)
import numpy as np x = np.arange(12, 38) print("原始数组:") print(x) print("翻转数组:") x = x[::-1] print(x)
5.数组操作
5.1连接数组
5.1.1 concatenate 函数
concatenate 函数沿指定的轴连接多个数组,他的语法格式如下:
#a1,a2 是要连接的数组,除了连接指定轴外,其他轴大小(元素个数)相同。
#axis 是沿指定轴的索引,默认为 0。
numpy.concatenate((a1, a2, ...), axis=0)
a = np.array([[1, 2],
[3, 4]])
b = np.array([[5, 6]])
#沿着哪种连接,就是哪轴的shape值发生变化
ab = np.concatenate((a, b))
print(ab)
ab = np.concatenate((a, b.T), axis=1)
print(ab)
沿着哪个轴拼,拼接前会检查剩余轴shape是否相同,不同拼接失败。
拼接后沿哪个轴拼接哪个轴shape就变,剩余轴的shape不变。
5.1.2 hstack 函数
hstack函数沿水平堆叠多个数组,相当于concatenate函数axis=1情况, 他的语法格式如下:
numpy.hstack(tup)
import numpy as np
a = np.array([[1, 2],
[3, 4]])
print(a.shape)
#要求0轴元素个数相同
b = np.array([[5], [7]])
print(b.shape)
print(np.hstack((a,b)))
注意:要求0轴元素个数相同
5.1.3 vstack 函数
vstack函数沿垂直堆叠多个数组,相当于concatenate函数axis=0情况,他的语法格式如下:
numpy.vstack(tup)
import numpy as np
a = np.array([[1, 2],
[3, 4]])
print(a.shape)
b = np.array([[5,7]])
print(b.shape)
print(np.vstack((a,b)))
注意:要求1轴上元素个数相同。
5.2分割数组
5.2.1 split 函数
split 函数沿指定轴分割多个数组,他的语法格式如下:
'''
ary 是要被分割的数组
indices_or_sections 是一个整数或数组,如果是整数就用该数平均分割;如果是数组,则为沿指定轴切片操作(注意左闭右开)
axis 是轴的分割方向,默认为 0
'''
numpy.split(ary, indices_or_sections, axis=0)
import numpy as np
a = np.arange(9)
b = np.split(a, 3)
print(b)
c = np.split(a, [4, 7])
print(c)
import numpy as np
a = np.arange(9).reshape(3, 3)
b = np.split(a, 3, axis=0)
print(b)
c = np.split(a, 3, axis=1)
print(c)
5.2.2 hsplit 函数
hsplit 函数沿水平方向分割数组,相当于 split 函数 axis=1 情况,他的 语法格式如下:
numpy.hsplit(ary, indices_or_sections)
import numpy as np
a = np.arange(9).reshape(3, 3)
b = np.hsplit(a, 3)
print(b)
5.2.3 vsplit 函数
vsplit 函数沿垂直方向分割数组,相当于 split 函数 axis=0 情况,他的语法格式如下:
numpy.vsplit(ary, indices_or_sections)
import numpy as np
a = np.arange(9).reshape(3, 3)
b = np.vsplit(a, 3)
print(b)
5.3算术运算
NumPy 数组对象可以使用 Python 原生的算术运算符,加、减、乘、除都可以使用。
import numpy as np
a = np.array([[1, 2],
[3, 4]])
b = np.array([[5, 6],
[7, 8]])
print(a+b)
print(a+10)
print(a*b)
print(a*10)
5.4广播
不同的形状数组或标量计算时发生广播。
5.4.1 标量广播
import numpy as np
a = np.array([1, 2, 3, 4])
print(a*10)
b = np.array([[5, 6],
[7, 8]])
print(b*10)
5.4.2 数组广播
import numpy as np
a = np.array([1, 2])
b = np.array([[5, 6],
[7, 8]])
print(a+b)
广播规则:
- 如果两个数组维度不相等,维度较低的数组的形状(shape)会从左侧开始填充 1,直到维度与高维数组相等。
- 如果两个数组维度相等时,要么对应轴的长度相同,要么其中一个长度为 1,则是兼容数组可以广播。长度为 1 的轴会被扩展。
练习:
-
编写一个 NumPy 程序,将华氏度的值转换为摄氏度。华氏度值存储在 NumPy 数组中 [0,12,45.21,34,99.91]。注:C = (5(F - 32)) / 9,C 是 摄氏度,F 是华氏度。
import numpy as np fvalues = [0, 12, 45.21, 34, 99.91] F = np.array(fvalues) print("华氏度数值:") print(F) C = (5*F/9 - 5*32/9) print("摄氏度数值:") print(C)
-
编写一个 NumPy 程序来连接两个二维数组。两个二维数组:[[0, 1, 3], [5, 7, 9]]和[[0, 2, 4], [6, 8, 10]]。
import numpy as np a = np.array([[0, 1, 3], [5, 7, 9]]) b = np.array([[0, 2, 4], [6, 8, 10]]) c = np.concatenate((a, b), 1) print(c)
-
编写一个 NumPy 程序将 9 个元素数组拆分为 3 个数组,每个数组分别包含 2 个、4 个和 3 个元素。
import numpy as np
x = np.arange(1, 10)
print("原始数组:",x)
print("分割后:")
print(np.split(x, [2, 6]))
- 编写一个 NumPy 程序,将形状 4x4 的数组拆分为沿第二轴的两个数组。
import numpy as np
x = np.arange(16).reshape((4, 4))
print("原始数组:",x)
print("分割后:")
print(np.hsplit(x,2))
6.numpy中的函数
官网文档:https://numpy.org/doc/stable/reference/routines.html
6.1 数学运算函数
6.1.1 算数运算函数
import numpy as np
a = np.array([1, 2])
b = np.array([[5, 6],
[7, 8]])
print(a+b)
print(np.add(a,b))
c = np.power(a, b)
print(c)
6.1.2 关系运算
import numpy as np
a = np.array([1, 2])
b = np.array([[5, 6],
[7, 8]])
print(np.equal(a,b))
print(np.less(a,b))
6.2随机数函数
6.2.1 常用随机数
# 返回一个(d0,d1,...,dn)形状的数组,元素的值介于[0.0,1.0)
numpy.random.rand(d0, d1, ..., dn)
#返回size形状的数组, 元素为介于[low, high)的随机整数,如果 high 省略则元素介于[0, low)随机整数
numpy.random.randint(self, low, high=None, size=None, dtype=None)
import numpy as np
a = np.random.rand(3,2)
print(a)
b = np.random.randint(5,10, size=(3, 2))
print(b)
6.2.2 正态分布随机数
#返回标准正态分布随机数, d0,d1...dn为shape
numpy.random.randn(d0, d1, ..., dn)。
#返回正态分布随机数,loc 平均值,scale 标准差, size为形状
numpy.random.normal(loc=0.0, scale=1.0, size=None)。
import numpy as np
a = np.random.randn(10)
print(a)
b = np.random.randn(3, 2)
print(b)
b = np.random.randint(5,10, size=(3, 2))
c = np.random.normal(1010, 30, size=(3, 2))
print(c)
6.3排序函数
6.3.1 轴排序
按照轴对数组进行排序函数 sort,他的语法格式如下:
'''
a 要排序的数组。
axis 排序的轴索引,默认是-1 表示最后一个轴。
kind 排序类型。'quicksort'(快速排序)默认值最快。另外,'mergesort'(归并排序)和'heapsort'(堆排序)
order 排序字段
'''
numpy.sort(a, axis=-1, kind='quicksort', order=None)
import numpy as np
a = np.random.randint(0, 10, size=(3, 4))
print(a)
b = np.sort(a)
print(b)
c = np.sort(a, axis=0)
print(c)
6.3.2 轴排序索引
按照轴对数组进行排序索引函数 argsort,他的语法格式如下:
numpy.argsort(a, axis=-1, kind='quicksort', order=None)
import numpy as np
a = np.random.randint(0, 10, size=(3, 4))
print(a)
bidx = np.argsort(a)
print(bidx)
cidx = np.argsort(a, axis=0)
print(cidx)
6.4 聚合函数
可以对整个数组元素或对轴元素进行计算,获得单一值,这是聚合函数。
如:sum、amin、amax、mean(平均值)、average(加权平均值)、var(方差)、std(标准偏差)等。
6.4.1 求和
求和函数可以使用 numpy.sum 函数或数组的 numpy.ndarray.sum 方法.
'''
a 要求和的数组。
axis 指定轴索引,如果 axis 没有指定是所有元素之和,如果指定轴则是该轴上的所有元素之和。
'''
numpy.sum(a, axis=None)
#类似上面的函数
numpy.ndarray.sum(axis=None)
import numpy as np
a = np.array([[5, 6],
[7, 8]])
np.sum(a)
np.sum(a, axis=-1)
np.sum(a, axis=0)
6.4.2 最大值
求最大值可以使用 numpy.amax 函数、numpy.nanmax 函数或数组的 ndarray.max 方法。
numpy.amax(a, axis=None)
#忽略 NaN(Not a Number,非数)
numpy.nanmax(a, axis=None)
#类似于amax
numpy.ndarray.max(axis=None)
import numpy as np
a = np.array([[5, 6],
[7, 8]])
print(np.amax(a))
print(np.amax(a, axis=-1))
print(np.amax(a, axis=0))
print(a.max())
b = np.array([[5, 6],
[7, np.nan]])
print(np.nanmax(b))
6.4.3 最小值
求最小值可以使用 numpy.amin 函数、numpy.nanmin 函数或数组的 ndarray.min 方法。
numpy.ammin(a, axis=None)
#忽略 NaN
numpy.nanmin(a, axis=None)
numpy.ndarray.min(axis=None)
import numpy as np
a = np.array([[5, 6],
[7, 8]])
print( np.amin(a))
print(np.amin(a, axis=-1))
print(np.amin(a, axis=0))
print(a.amin())
6.4.4 mean(平均值)
平均值 可 以使 用 numpy.mean 函 数 、 numpy.nanmean 函 数 或 数组 的 numpy.ndarray.mean 方法。
numpy.mean(a, axis=None)
numpy.nanmean(a, axis=None)
numpy.ndarray.mean(axis=None)
import numpy as np
a = np.array([[5, 6],
[7, 8]])
print( np.mean(a))
print(np.mean(a, axis=-1))
print(np.mean(a, axis=0))
print(a.mean())
6.4.5 average(加权平均值)
加权平均值可以使用 numpy.average 函数,语法如下
numpy.average(a, axis=None, weights=None)
import numpy as np
a = np.array([[5, 6],
[7, 8]])
print(np.average(a))
print(np.average(a, axis=0))
print(np.average(a, axis=-1))
print(np.average(a, axis=0, weights=[0.3,0.7]))
6.5 unique 函数
unique 函数可以剔除数组中重复的元素,并按照从小到大的顺序排列。语法如下:
'''
ar 原始数组。
return_index 设置为 Ture,返回原始数组中的索引数组。
axis 指定轴索。如果没有指定,多维数组会平展进行排序。
'''
numpy.unique(ar, return_index=False, axis=None)
import numpy as np
L = [x for x in 'Hello']
a = np.array(L)
u = np.unique(a)
print(u)
u, idx = np.unique(a, return_index=True)
print(idx)
import numpy as np
a = np.array([[1, 0, 0],
[1, 0, 0],
[2, 1, 4]])
u = np.unique(a)# 没有指定轴,展开数组进行处理
print(u)
u = np.unique(a, axis=0) # 指定0轴,剔除0轴上重复的一维数组
print(u)
6.6 where 函数
where 函数相当于三元运算符,他的语法格式如下:
'''
condition 是条件,如果为 True 返回 x,否则返回 y。
x 和 y 可以是标量或数组。
'''
numpy.where(condition[, x, y])
import numpy as np
a = np.arange(5)
b = np.where(a < 3, a, a + 100)
print(b) # array([ 0, 1, 2, 103, 104])
6.7 flatten
import numpy as np
a = np.random.randint(0, 10, size=(3, 4))
print(a)
print(a.flatten())
6.8 自定义通用函数(了解)
自定义通用函数(ufunc)数组操作将用于数组中的每一个元素,他的语法 格式如下:
'''
func 任何 Python 函数,可以是内置的也可以是自定义函数。
nin 传入数组参数个数
nout 返回数组个数
'''
ufunc = numpy.frompyfunc(func, nin, nout)
该函数返回一个自定义的通用函数,他的类型是 numpy.ufunc。
import numpy as np
# 定义通用函数abs_ufunc,abs是Python内置函数
abs_ufunc = np.frompyfunc(abs, 1, 1)
a = np.array([[-6, 8],
[ -8, -10]])
# 调用通用函数abs_ufunc
b = abs_ufunc(a)
print(b)
import numpy as np
# 定义add_sub函数实现两个数+和-运算,返回元组
def add_sub(x, y):
return x + y, x - y
# 定义通用函数add_sub_ufunc
add_sub_ufunc = np.frompyfunc(add_sub, 2, 2)
a = np.array([1, 2])
b = np.array([[5, 6],
[7, 8]])
# 调用通用函数add_sub_ufunc
add, sub = add_sub_ufunc(a, b)
print(add)
print(sub)
练习:
-
写一个 NumPy 程序比较两个数组。
import numpy as np a = np.array([1, 2]) b = np.array([4, 5]) print("Array a: ",a) print("Array b: ",b) print("a > b") print(np.greater(a, b)) print("a >= b") print(np.greater_equal(a, b)) print("a < b") print(np.less(a, b)) print("a <= b") print(np.less_equal(a, b))
-
写一个 NumPy 程序自定义一个通用函数,实现两个数组元素的翻倍计算。
import numpy as np # 定义double函数 def double(x): return 2 * x # 定义通用函数double_ufunc double_ufunc = np.frompyfunc(double, 1, 1) a = np.array([1, 2]) # 调用通用函数double_ufunc b = double_ufunc(a) print(b)
-
编写 NumPy 程序以获取数组的唯一元素。
import numpy as np x = np.array([10, 10, 20, 20, 30, 30]) print("原始数组:") print(x) print("唯一元素的数组:") print(np.unique(x)) x = np.array([[1, 1], [2, 3]]) print("原始数组:") print(x) print("唯一元素的数组:") print(np.unique(x))
-
编写 NumPy 程序从数组中沿给定轴取出最大值和最小值。
import numpy as np x = np.array([1, 2, 3, 4, 5, 6]) print("原始数组: ",x) print("最大值: ",np.amax(x)) print("最小值: ",np.amin(x))
-
编写一个 NumPy 程序,对数组[[4,6],[2,1]]的第一个轴和最后一个轴进行排序。
import numpy as np a = np.array([[4, 6],[2, 1]]) print("原始数组:") print(a) print("沿第一轴排序:") x = np.sort(a, axis=0) print(x) print("沿最后一个轴排序:") y = np.sort(x, axis=-1) print(y)
7.线性代数
NumPy 提供线性代数计算模块 numpy.linalg,该模块包含了线性代数所需的所有功能。
7.1 矩阵点积
点积(Dot Product),作为向量间的一种基本运算,通过对应元素相乘后求和来刻画两个向量的相似度和方向关系。
点积也称为内积或数量积 。
点积运算要求前一个矩阵的列数和第一个矩阵的行数相等。
#numpy中完成点积运算的两种方式
numpy.dot(a, b, out=None)
ndarray.dot(b, out=None)
a = np.arange(1,10).reshape(3,3)
b = np.ones((3,2), dtype=np.int8)
np.dot(a,b)
#a.dot(b)
7.2 矩阵叉积
叉积, 也称为向量积或外积 。
矩阵对应元素相乘。
a = np.ones((4,3))
b = a +1
print(a*b)
7.3 矩阵行列式
2 阶行列式公式如下:
矩阵行列式函数 numpy.linalg.det,语法如下:
numpy.linalg.det(a)
import numpy as np
a = np.array(((1,2),(5,6)))
print(np.linalg.det(a))
7.4 逆矩阵
逆矩阵:AB=BA=E,则称 B 是 A 的逆矩阵,而 A 则被称为可逆矩阵。E 为单位矩阵。
numpy.linalg.inv(a)
import numpy as np
A = np.array([[1, 2],
[3,4]])
B = np.linalg.inv(A)
print(B)
E = np.dot(A,B)
print(E)
练习:
-
编写一个 NumPy 程序来计算两个给定矩阵的内积。两个矩阵如下:
[[1, 0], [0, 1]]
[[1, 2], [3, 4]]
import numpy as np p = [[1, 0], [0, 1]] q = [[1, 2], [3, 4]] print("原始数组矩阵:") print(p) print(q) result = np.dot(p, q) print("矩阵乘法的结果:") print(result)
-
编写 NumPy 程序来计算给定方阵的行列式
import numpy as np from numpy import linalg as LA a = np.array([[1, 0], [1, 2]]) print("原始数组矩阵:") print(a) print("矩阵行列式:") print(LA.det(a))
8.高维数组
8.1 创建高维数组
-
创建三维数组
import numpy as np a = np.array([[[10, 11, 12], [13, 14, 15], [16, 17, 18]], [[20, 21, 22], [23, 24, 25], [26, 27, 28]], [[30, 31, 32], [33, 34, 35], [36, 37, 38]]]) print(a)
-
创建四维数组:
import numpy as np b = np.arange(81).reshape(3, 3, 3, 3) print(b)
8.2 访问高维数组元素
8.2.1 索引访问高维数组
多维数组索引访问有两种表达式:
- 表达式1:np.array[0轴索引][1轴索引]…[n-1轴索引]
- 表达式2:np.array[0 轴索引, 1轴索引,…, n-1轴索 引]
索引访问三维数组元素 a[i, j, k]:
- a[i, j, k]返回单个数值(标量)
- a[i, j] 返回一维数组(向量)
- a[i] 返回二维数组(矩阵)
8.2.2 切片访问高维数组
语法格式和二维数组类似:
np.array[所在 0 轴切片, 所在 1 轴切片,..., 所在 n-1 轴切片]
import numpy as np
a = np.array([[[10, 11, 12],
[13, 14, 15],
[16, 17, 18]],
[[20, 21, 22],
[23, 24, 25],
[26, 27, 28]],
[[30, 31, 32],
[33, 34, 35],
[36, 37, 38]]])
print(a[:, 1, 2])
print(a[:, 1])
print(a[...,0])
print(a[:2,1:,:2])
练习:
- 编写一个 NumPy 程序来创建一个 3x3x3 数组,并填充任意值。
import numpy as np
x = np.random.random((3, 3, 3))
print(x)
9.数组的保存与读取
9.1 数组的保存
NumPy 数组可以保存到二进制或文本文件中,保存到二进制文件函数如下:
'''
file 文件名/文件路径
arr 要存储的数组
allow_pickle布尔值,允许使用Python pickles保存对象数组(可选参数,默认即可)
fix_imports 为了方便 Pyhton2 中读取 Python3 保存的数据(可选参数,默认即可)
'''
numpy.save(file, arr, allow_pickle=True, fix_imports=True)
numpy.savez(file, *args, **kwds)
numpy.savez_compressed(file, *args, **kwds)
a = np.arange(9).reshape(3, 3)
np.save('arry_save1', a)
b = np.arange(10)
np.savez('arry_savez1', arry_a=a, arry_b=b)
np.savez_compressed(file, *args, **kwds)
9.2 数组的读取
NumPy 数组读取二进制文件函数 load,语法格式如下:
numpy.load(file, mmap_mode=None, allow_pickle=True, fix_imports=True, encoding='ASCII')
import numpy as np
a1 = np.load('arry_save1.npy')
print(a1)
data = np.load('arry_savez1.npz')
print(data['arry_a'])
print(data['arry_b'])
data = np.load('arry_savez_compressed1.npz')
print(data['arry_a'])
print(data['arry_b'])
练习:
- 编写一个 NumPy 程序,将两个给定的数组以压缩格式(.npz 格式)保存到一个文件中并加载它。
import numpy as np
import os
x = np.arange(10)
y = np.arange(11, 20)
print("原始数组:")
print(x)
print(y)
np.savez('temp_arra.npz', x=x, y=y)
print("加载数组从'temp_arra.npz'文件:")
with np.load('temp_arra.npz') as data:
x2 = data['x']
y2 = data['y']
print(x2)
print(y2)
[23, 24, 25],
[26, 27, 28]],
[[30, 31, 32],
[33, 34, 35],
[36, 37, 38]]])
print(a[:, 1, 2])
[外链图片转存中...(img-OkePg4ZK-1718006784881)]
```python
print(a[:, 1])
[外链图片转存中…(img-tvu74nlV-1718006784881)]
print(a[...,0])
[外链图片转存中…(img-DFdmROEb-1718006784882)]
print(a[:2,1:,:2])
[外链图片转存中…(img-3SIuvoBx-1718006784882)]
练习:
- 编写一个 NumPy 程序来创建一个 3x3x3 数组,并填充任意值。
import numpy as np
x = np.random.random((3, 3, 3))
print(x)
9.数组的保存与读取
9.1 数组的保存
NumPy 数组可以保存到二进制或文本文件中,保存到二进制文件函数如下:
'''
file 文件名/文件路径
arr 要存储的数组
allow_pickle布尔值,允许使用Python pickles保存对象数组(可选参数,默认即可)
fix_imports 为了方便 Pyhton2 中读取 Python3 保存的数据(可选参数,默认即可)
'''
numpy.save(file, arr, allow_pickle=True, fix_imports=True)
numpy.savez(file, *args, **kwds)
numpy.savez_compressed(file, *args, **kwds)
a = np.arange(9).reshape(3, 3)
np.save('arry_save1', a)
b = np.arange(10)
np.savez('arry_savez1', arry_a=a, arry_b=b)
np.savez_compressed(file, *args, **kwds)
9.2 数组的读取
NumPy 数组读取二进制文件函数 load,语法格式如下:
numpy.load(file, mmap_mode=None, allow_pickle=True, fix_imports=True, encoding='ASCII')
import numpy as np
a1 = np.load('arry_save1.npy')
print(a1)
data = np.load('arry_savez1.npz')
print(data['arry_a'])
print(data['arry_b'])
data = np.load('arry_savez_compressed1.npz')
print(data['arry_a'])
print(data['arry_b'])
练习:
- 编写一个 NumPy 程序,将两个给定的数组以压缩格式(.npz 格式)保存到一个文件中并加载它。
import numpy as np
import os
x = np.arange(10)
y = np.arange(11, 20)
print("原始数组:")
print(x)
print(y)
np.savez('temp_arra.npz', x=x, y=y)
print("加载数组从'temp_arra.npz'文件:")
with np.load('temp_arra.npz') as data:
x2 = data['x']
y2 = data['y']
print(x2)
print(y2)