文章目录
1. Numpy 介绍
Numpy(Numerical Python),是 Python 科学计算的基础包。Mumpy 主要提供了以下内容:
- 快速高效的多维数组对象 ndarray。
- 对数组执行元素级计算以及直接对数组执行科学计算的函数。
- 线性代数、傅里叶变换及随机数生成的功能。
- 将 C、C++、Fortran 代码集成到 Python 的工具。
- 读写硬盘上基于数组数据集的工具。
Numpy 是用于科学计算的基础模块,不但能够完成科学计算的任务,而且能够被用作高效的多维数据容器,可以用于存储和处理大型矩阵。Numpy 的数据容器可以保存任意类型的数据,所以可以整合各种数据。
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 会实行广播机制。
广播机制四个原则:
- 让所有输入数组向其中 shape 最长的数组看齐,shape 中不足的部分通过在前面加 1 补齐。
- 输出数组的 shape 是输入数组 shape 的各个轴上的最大值。
- 如果输入数组的某个轴和输出数组的对应轴的长度相同或者长度为 1 ,则这个数组能够用来计算,否则出错。
- 当输入数组的某个轴的长度为 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)
np.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding='ASCII')
# 二进制数据存储
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)
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))