Python 的 Numpy 数值计算

1. Numpy 介绍

  Numpy(Numerical Python),是 Python 科学计算的基础包。Mumpy 主要提供了以下内容:

  • 快速高效的多维数组对象 ndarray。
  • 对数组执行元素级计算以及直接对数组执行科学计算的函数。
  • 线性代数、傅里叶变换及随机数生成的功能。
  • 将 C、C++、Fortran 代码集成到 Python 的工具。
  • 读写硬盘上基于数组数据集的工具。

  Numpy 是用于科学计算的基础模块,不但能够完成科学计算的任务,而且能够被用作高效的多维数据容器,可以用于存储和处理大型矩阵。Numpy 的数据容器可以保存任意类型的数据,所以可以整合各种数据。

Numpy 官网介绍
Numpy 1.17 官方手册

2. Numpy 数组

  Python 提供了一个 array 模块。array 和 list 不同,它直接保存数值,和 C 语言的一位数组比较类似。但是由于 Python 的 array 模块不支持多维,也没有各种运算函数,所以也不适合做数值运算。Numpy 提供了一种存储单一数据类型的多维数组——ndarray。
  Numpy 提供了两种基本对象:ndarray(N-dimensional Array Object)和 ufunc(Universal Function Object)。ndarray 是存储单一数据类型的多维数组,而 ufunc 是能够对数组进行处理的函数。

2.1 数组属性

常用属性 说明
shape 返回 tuple,返回数组维度的元组。如:(m,n) ,表示 m 行 n 列
ndim 返回 int,表示数组的维度
size 返回 int,表示数组中元素的个数
dtype 返回 data-type,表示数组元素的数据类型
itemsize 返回 int,表示一个数组元素的大小(以字节为单位)
nbytes 返回 int,表示数组元素消耗的总字节数

2.2 创建数组

numpy.array(object,dtype=None,cope=True,order='K',subok=False,ndimn=0)

官方文档

# 导入Numpy库
import numpy as np

# 创建一维数组
arr1 = np.array([1,2,3,4])
print('创建的一维数组为:',arr1)

# 创建二维数组
arr2 = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print('创建的二维数组为:\n',arr2)

# 查看数组属性
print('数组的维数为:',arr2.ndim)
print('数组的维度为:',arr2.shape)
print('数组的元素个数为',arr2.size)
print('数组的元素类型为',arr2.dtype)
print('数组每个元素的大小为',arr2.itemsize)
print('数组元素消耗的总字节数为',arr2.nbytes)

# 重新设置数组的shape属性
arr2.shape = 4,3
print('重新设置 shape 后的 arr2 为:\n',arr2)

在这里插入图片描述
  上面的例子都是创建一个 Python 序列,然后通过 array 函数转换为数组,这样做效率不高,因此 Numpy 提供了许多专门用来创建数组的函数。

# 使用arange函数创建数组(开始值,终值,步长(不包括终值))
print('使用arange函数创建的数组为:\n',np.arange(0,1,0.1))

# 使用linspace函数创建数组(开始值,终值,元素个数(包括终值))
print('使用linspace函数创建的数组为:\n',np.linspace(0,1,10))

# 使用logspace函数创建等比数列(开始值(1——10^1),终值,元素个数(包括终值)))
print('使用logspace函数创建等比数列为:\n',np.logspace(1,2,10))
	
# 特殊数组
print('使用zeros函数创建的全0数组为:\n',np.zeros((2,3)))
print('使用ones函数创建的全1数组为:\n',np.ones((2,3)))
print('使用eye函数创建的数组为:\n',np.eye(3))
print('使用diag函数创建的数组为:\n',np.diag([1,2,3,4]))

在这里插入图片描述
数组数据类型转换

# 数组数据类型转换
print('转换结果为:',np.float(42))
print('转换结果为:',np.int8(42.0))
print('转换结果为:',np.bool(42))
print('转换结果为:',np.bool(0))
print('转换结果为:',np.float(True))
print('转换结果为:',np.float(False))

在这里插入图片描述

2.3 生成随机数

# 生成随机数([0,1))
print('生成随机数组为:\n',np.random.random(10))
print('生成服从均匀分布的随机数组为:\n',np.random.rand(3,4))
print('生成服从正态分布的随机数组为:\n',np.random.randn(3,4))

# 生成随机数(给定范围(不包括上限))
print('生成给定上下限的随机数组为:\n',np.random.randint(2,10,size=[2,5]))

在这里插入图片描述

2.4 访问数组元素

# 使用索引访问一维数组
arr = np.arange(10)
print('创建的一维数组为:',arr)
print('索引结果为:',arr[5])
print('索引结果为:',arr[:5])
print('索引结果为:',arr[5:])
print('索引结果为:',arr[-1])      # 数组最后一个元素
print('索引结果为:',arr[3:5])
print('索引结果为:',arr[1:-1:2])  # 第三个参数为步长
print('索引结果为:',arr[5:1:-2])  # 步长为负数时,开始下标必须大于结束下标
arr[2:4] = 100,101
print('修改后的一维数组为:',arr)  # 下标还可以修改元素的值

# 使用索引访问多维数组
arr = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print('创建的二维数组为:\n',arr)
print('索引结果为:',arr[0,2:4])   # 索引第0行中的第2列和第3列元素
print('索引结果为:',arr[1:,1:])
print('索引结果为:',arr[:,2])
print('索引结果为:',arr[1,(0,2,3)])

在这里插入图片描述

2.5 变换数组的形态

# 改变数组形状(reshape函数改变原始数组形状的同时不改变原始数据的值)
arr = np.arange(12)
print('创建的一维数组为:',arr)
print('新的数组为:\n',arr.reshape(3,4))

# 使用ravel函数展平数组
arr = np.arange(12).reshape(3,4)
print('创建的二维数组为:\n',arr)
print('数组展平后:',arr.ravel())

# 使用flatten函数展平数组(可以选择横向或纵向)
print('数组横向展平后:',arr.flatten())
print('数组纵向展平后:',arr.flatten('F'))

# 使用hstack函数和vstack函数实现数组横向与纵向组合
arr1 = np.arange(12).reshape(3,4)
print('创建的数组1为:\n',arr1)
arr2 = arr1*3
print('创建的数组2为:\n',arr2)
print('横向组合为:\n',np.hstack((arr1,arr2)))
print('纵向组合为:\n',np.vstack((arr1,arr2)))

# 使用concatenate函数实现数组横向与纵向组合,axis默认为0,纵向
print('横向组合为:\n',np.concatenate((arr1,arr2),axis=1))
print('纵向组合为:\n',np.concatenate((arr1,arr2),axis=0))

# 使用hsplit函数和vsplit函数实现横向与纵向分割数组,平均分割
arr = np.arange(16).reshape(4,4)
print('创建的二维数组为:\n',arr)
print('横向分割为:\n',np.hsplit(arr,2))
print('纵向分割为:\n',np.vsplit(arr,2))

# 使用split函数实现横向与纵向分割数组,平均分割
print('横向分割为:\n',np.split(arr,2,axis=1))
print('纵向分割为:\n',np.split(arr,2,axis=0))

在这里插入图片描述

3. Numpy 矩阵和通用函数

  在 Numpy 中,矩阵(matrix)是数组(ndarray)的子类。矩阵是继承数组对象的二维数组对象。注意:官方文档中不再建议使用此类,即使对于线性代数也是如此。而是使用常规数组,将来可能会删除此类!

3.1 矩阵属性

说明:因为矩阵继承自数组,所以矩阵具有数组的所有的属性,以下展示矩阵特有的属性。

常用属性 说明
T 返回自身的转置矩阵
H 返回自身的共轭矩阵
I 返回自身的逆矩阵
A 返回自身数据的二维数组的一个视图
A1 返回自身数据一维数组的一个视图(展开)

3.2 创建矩阵

# 使用mat函数和matrix函数创建矩阵
matr1 = np.mat("1 2 3;4 5 6;7 8 9")  # 使用分号隔开数据
print('创建的矩阵1为:\n',matr1)
matr2 = np.matrix([[1,2,3],[4,5,6],[7,8,9]])
print('创建的矩阵2为:\n',matr2)

# 使用bmat函数创建矩阵(小矩阵合成大矩阵)
print('创建的矩阵3为:\n',np.bmat("matr1 matr2;matr1 matr2"))

# 矩阵运算
print('矩阵数乘的结果为:\n',matr1*3)
print('矩阵相加的结果为:\n',matr1+matr2)
print('矩阵相减的结果为:\n',matr1-matr2)
print('矩阵相乘的结果为:\n',matr1*matr2)
print('矩阵对应元素相乘的结果为:\n',np.multiply(matr1,matr2))

# 查看矩阵属性
print('矩阵1的转置矩阵为:\n',matr1.T)
print('矩阵1的共轭转置矩阵为:\n',matr1.H)  # 实数的共轭就是其本身
print('矩阵1的逆矩阵为:\n',matr1.I)
print('矩阵1的二维数组为:\n',matr1.A)
print('矩阵1的一维数组为:',matr1.A1)

在这里插入图片描述

3.3 ufunc 函数

   ufunc 函数全称为通用函数,是一种能够对数组中所有元素进行操作的函数。ufunc 函数是针对数组进行操作,并以 Numpy 数组作为输出,因此不需要对数组每一个元素都进行操作。所以使用 ufunc 函数比使用 math 库中函数高效的多。

3.3.1 常用 ufunc 函数运算

  常用的 ufunc 函数有四则运算、比较运算和逻辑运算。

# 数组的四则运算
x = np.array([1,3,5])
y = np.array([2,3,4])
print('数组相加的结果为:',x + y)
print('数组相减的结果为:',x - y)
print('数组相乘的结果为:',x * y)
print('数组相除的结果为:',x / y)
print('数组幂运算的结果为:',x ** y)

# 数组的比较运算
print('数组比较的结果为:',x < y)
print('数组比较的结果为:',x > y)
print('数组比较的结果为:',x == y)
print('数组比较的结果为:',x >= y)
print('数组比较的结果为:',x <= y)
print('数组比较的结果为:',x != y)

# 数组的逻辑运算,np.all()表示and,np.any()表示or
print("数组逻辑运算结果为:",np.all(x == y))
print("数组逻辑运算结果为:",np.any(x == y))

在这里插入图片描述

3.3.2 ufunc 函数的广播机制

  广播(Broadcasting)是指不同形状的数组之间执行算数运算的方式。当使用 ufunc 函数进行数组计算时,ufunc 函数会对两个数组的对应元素进行计算。进行这种运算的前提是两个数组的 shape 一致。若两个数组的 shape 不一致,则 Numpy 会实行广播机制。

广播机制四个原则:

  1. 让所有输入数组向其中 shape 最长的数组看齐,shape 中不足的部分通过在前面加 1 补齐。
  2. 输出数组的 shape 是输入数组 shape 的各个轴上的最大值。
  3. 如果输入数组的某个轴和输出数组的对应轴的长度相同或者长度为 1 ,则这个数组能够用来计算,否则出错。
  4. 当输入数组的某个轴的长度为 1 时,沿着此轴运算时使用此轴的第一组值。
# 一维数组的广播机制
arr1 = np.array([[0,0,0],[1,1,1],[2,2,2],[3,3,3]])
print('创建的数组1为:\n',arr1)
print('数组1的形状为:',arr1.shape)
arr2 = np.array([1,2,3])
print('创建的数组2为:\n',arr2)
print('数组2的形状为:',arr2.shape)
print('数组1和2相加的结果为:\n',arr1 + arr2)
arr3 = np.array([2])
print('创建的数组3为:\n',arr3)
print('数组3的形状为:',arr3.shape)
print('数组1和3相加的结果为:\n',arr1 + arr3)

print("--------------------------------------")

# 二维数组的广播机制
arr1 = np.array([[0,0,0],[1,1,1],[2,2,2],[3,3,3]])
print('创建的数组1为:\n',arr1)
print('数组1的形状为:',arr1.shape)
arr2 = np.array([1,2,3,4]).reshape(4,1)
print('创建的数组2为:\n',arr2)
print('数组2的形状为:',arr2.shape)
print('数组1和2相加的结果为:\n',arr1 + arr2)

在这里插入图片描述

4. 利用 Numpy 进行统计分析

4.1 读/写文件

save 函数以二进制的格式保存数据(文件扩展名 .npy,若将多个数组保存到一个文件,可以使用 savez 函数,文件扩展名 .npz),load 函数从二进制的文件中读取数据。

np.save(file, arr, allow_pickle=True, fix_imports=True)

save 函数官方文档

np.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding='ASCII')

load 函数官方文档

# 二进制数据存储
arr = np.arange(100).reshape(10,10)
np.save("save_arr",arr)

# 多个数组存储
arr1 = np.array([[1,2,3],[2,3,4]])
arr2 = np.arange(0,1.0,0.1)
np.savez("savez_arr",arr1,arr2)

# 二进制文件读取
loaded_data = np.load("save_arr.npy")
print('读取的数组为:\n',loaded_data)

# 读取含有多个数组的文件
loaded_data1 = np.load("savez_arr.npz")
print('读取的数组1为:\n',loaded_data1['arr_0'])
print('读取的数组2为:\n',loaded_data1['arr_1'])

在这里插入图片描述
  在实际的数据分析中,更多地使用文本格式的数据,如 .txt,.csv 格式,因此使用 savetxt 函数、loadtxt 函数、genfromtxt 函数执行对文本格式数据的读取任务。

np.savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='n', header='', footer='', 
			comments='# ', encoding=None)

savetxt 函数官方解释

  loadtxt 函数执行相反的操作,即把文件加载到一个二维数组。genfromtxt 函数和 loadtxt 函数相似,但它面向的是结构化数组和缺失数据。

# 文件存储与读取
arr = np.arange(0,12,0.5).reshape(4,-1)  # 一个形状的尺寸可以是-1,在这种情况下,该值是从数组的长度和剩余维度推断出来
print('创建的数组为:\n',arr)
np.savetxt("arr.txt",arr,fmt="%d",delimiter=",")  # fmt="%d" 表示保存为整数
loaded_data = np.loadtxt("arr.txt",delimiter=",")
print('读取的数组为:\n',loaded_data)

# 使用 genfromtxt 函数读取数组
loaded_data = np.genfromtxt("arr.txt",delimiter=",")
print('读取的数组为:\n',loaded_data)

在这里插入图片描述

4.2 使用函数进行简单的统计分析

4.2.1 排序

  Numpy 的排序有两种方式,分别为 直接排序间接排序。直接排序是指对数值直接排序;间接排序是指根据一个或多个键对数据集进行排序。在 Numpy 中,直接排序经常使用 sort 函数,间接排序经常使用 argsort 函数和 lexsort 函数。

# 使用sort函数进行排序(无返回值,原始数据会改变)
np.random.seed(42)  # 设置随机种子
arr = np.random.randint(1,10,size = 10)
print("创建的随机数组为:\n",arr)
arr.sort()
print('排序后的数组为:\n',arr)
arr = np.random.randint(1,10,size = (3,3))
print('创建的数组为:\n',arr)
arr.sort(axis = 1)      # 沿着横轴排序
print('排序后的数组为:\n',arr)
arr.sort(axis = 0)      # 沿着纵轴排序
print('排序后的数组为:\n',arr)

# 使用 argsort 函数进行排序(返回值为索引数组,是重新排序值的下标)
arr = np.array([2,3,6,8,0,7])
print('创建的数组为:',arr)
print('排序后的数组为:\n',arr.argsort())  

# 使用lexsort函数进行排序(返回值为索引数组,可以一次性对满足多个键的数组执行间接排序)
# 序列中的最后一个键用于主排序顺序、辅助排序顺序的倒数第二个键等。
a = np.array([3,2,6,4,5])
b = np.array([50,30,40,20,10])
c = np.array([400,300,600,100,200])
d = np.lexsort((a,b,c))
print('排序后的数组为:\n',list(zip(a[d],b[d],c[d])))

在这里插入图片描述

4.2.2 去重与重复数据

# 数组内数据去重
arr = np.array([1,1,2,3,4,5,5])
print('创建的数组为:\n',arr)
print('去重后的数组为:\n',np.unique(arr))
print('去重后的数组为:\n',sorted(set(arr)))  # 跟np.unique等价的代码

# 使用tile函数实现数据重复
arr = np.arange(5)
print('创建的数组为:\n',arr)
print('重复后数组为:\n',np.tile(arr,3))      # 第二个参数为重复的次数

# 使用repeat函数实现数据去重
np.random.seed(42)
arr = np.random.randint(0,10,size = (3,3))
print('创建的数组为:\n',arr)
print('重复后数组为:\n',arr.repeat(2,axis = 0))  # 按行进行元素重复
print('重复后数组为:\n',arr.repeat(2,axis = 1))  # 按列进行元素重复

在这里插入图片描述

4.2.3 常用的统计函数

# Numpy 中常用统计函数的使用
arr = np.arange(20).reshape(4,5)
print('创建的数组为:\n',arr)
print('数组的和为:',np.sum(arr))
print('数组纵轴的和为:',arr.sum(axis = 0))
print('数组横轴的和为:',arr.sum(axis = 1))
print('数组的均值为:',np.mean(arr))
print('数组纵轴的均值为:',arr.mean(axis = 0))
print('数组横轴的均值为:',arr.mean(axis = 1))
print('数组的标准差为:',np.std(arr))
print('数组的方差为:',np.var(arr))
print('数组的最小值为:',np.min(arr))
print('数组的最大值为:',np.max(arr))
print('数组的最小值的索引为:',np.argmin(arr))
print('数组的最大值的索引为:',np.argmax(arr))

# cumsum函数和cumprod函数的使用
arr = np.arange(2,10)
print('创建的数组为:',arr)
print('数组元素的累计和为:',np.cumsum(arr))
print('数组元素的累计积为:',np.cumprod(arr))

在这里插入图片描述

发布了14 篇原创文章 · 获赞 33 · 访问量 1530

猜你喜欢

转载自blog.csdn.net/weixin_42837961/article/details/104113718