目录
Python具有强大的数据处理能力,尤以数组处理为主。numpy包是科学计算库,提供N维数组运算及各种数据分析方法;scipy包需要numpy包支持,提供积分、方程组求解等运算;matplotlib包提供数据绘图命令,所绘图像质量较高;pandas包提供机器学习数据格式。
1 numpy数组使用
numpy、scipy、matplotlib这3个包通常一起使用,这种组合可用于替代MATLAB软件的功能,构成一个强大的科学计算环境,有助于我们通过Python学习数据科学或机器学习。
首先安装这3种包:
pip install numpy
pip install scipy
pip install matplotlib
1.1 numpy生成数组
numpy官网:http://www.numpy.org/
创建数组的方式有很多种,如可以通过将已有的元组、列表或range对象使用numpy.array()函数转换为数组的方式来生成数组。
numpy.array()函数的语法格式如下:
numpy.array(object,dtype = None,copy = True,order = None,subok = False,ndmin = 0)
#参数说明如下:
#object:表示数组或嵌套的数列;
#dtype:可选参数,表示数组元素的数据类型;
#copy:可选参数,表示对象是否需要复制;
#order:表示创建数组的样式,C为行方向,F为列方向,A为任意方向(默认);
#subok:表示默认返回一个与基类类型一致的数组;
#ndmin:表示指定生成数组的最小维度。
例1.1.1,使用numpy.array()函数将元组、列表或range对象转换成数组:
import numpy as np #导入numpy模块,并用np代替
a = (1,2,3,4,5)
b = [1,2,3,4,5]
c = [[1,2,3],[4,5,6]]
print(np.array(a)) #将元组转换成数组
print(np.array(b)) #将列表转换成数组
print(np.array(c)) #将列表转换成数组
print(np.array(range(5))) #将range对象转换成数组
运行结果如下:
[1 2 3 4 5]
[1 2 3 4 5]
[[1 2 3]
[4 5 6]]
[0 1 2 3 4]
我们还可以使用numpy.asarray()函数来创建数组。
numpy.asarray()函数的语法格式如下:
numpy.asarray(a,dtype = None,order = None)
#参数说明如下:
#a:表示数组或嵌套的数列;
#dtype:可选参数,表示数组元素的数据类型;
#order:表示创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)。
例1.1.2,使用numpy.asarray()函数将元组、列表或range对象转换成数组:
import numpy as np #导入numpy模块,并用np代替
a = (1,2,3,4,5)
b = [1,2,3,4,5]
c = [[1,2,3],[4,5,6]]
print(np.asarray(a)) #将元组转换成数组
print(np.asarray(b)) #将列表转换成数组
print(np.asarray(c)) #将列表转换成数组
print(np.asarray(range(5))) #将range对象转换成数组
运行结果如下:
[1 2 3 4 5]
[1 2 3 4 5]
[[1 2 3]
[4 5 6]]
[0 1 2 3 4]
通过观察例1.1.1和例1.1.2我们发现,numpy.array()函数和numpy.asarray()函数好像没有什么区别,下面我们通过一个例子来理解两者之间的区别。
例1.1.3,numpy.array()函数和numpy.asarray()函数的不同:
import numpy as np #导入numpy模块,并用np代替
A = np.ones((3,3))
print(A)
B = np.array(A)
print(B)
C = np.asarray(A)
print(C)
A[0] = 0
print('修改后的A:\n',A)
print('修改后的B:\n',B)
print('修改后的C:\n',C)
运行结果如下:
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
修改后的A:
[[0. 0. 0.]
[1. 1. 1.]
[1. 1. 1.]]
修改后的B:
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
修改后的C:
[[0. 0. 0.]
[1. 1. 1.]
[1. 1. 1.]]
可以发现,当修改了A数组中的第一行元素后,再分别输出A、B、C数组,其中B和C数组的结果并不是完全相同的。这是因为numpy.array()函数和numpy.asarray()函数都可以将结构数据转化为ndarray,但是当数据源是ndarray时,numpy.array()函数仍然会复制出一个副本,占用新的内存,而numpy.asarray()函数不会。
还可以通过其他方式生成数组,如numpy.zeros()函数、numpy.ones()函数、numpy.identity()函数、numpy.empty()函数、numpy.linspace()函数等。
numpy.zeros()函数用于生成一个元素全为0的数组。
numpy.zeros()函数语法格式如下:
numpy.zeros(shape,dtype = float,order = 'C')
numpy.ones()函数用于生成一个元素全为1的数组。
numpy.ones()函数语法格式如下:
numpy.ones(shape,dtype = None,order = 'C')
numpy.empty()函数用于创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组。
numpy.empty()函数语法格式如下:
numpy.empty(shape,dtype = float,order = 'C')
以上3种方式中,参数shape指定数组形状,即几行几列的数组;dtype指定数据类型;order指定在计算机内存中存储元素的顺序,C为行优先,F为列优先,默认为C。
numpy.identity()函数用于生成一个单位矩阵。
numpy.identity()函数语法格式如下:
numpy.identity(n,dtype = None)
其中,n为生成单位矩阵的维数。
numpy.linspace()函数用于创建一个一维数组,元素由等差数列构成。
numpy.linspace()函数语法格式如下:
numpy.linspace(start,stop,num=50,endpoint=True,retstep=False,dtype = None)
#参数说明如下:
#start:表示数列的第一个值;
#stop:表示数列的最后一个值;
#num:表示生成等步长数列的个数,默认为50;
#endpoint:表示值为True时,数列包含stop,否则不包含,默认为True;
#retstep:表示值为True时,生成数组中显示间距,否则不显示;
#dtype:表示ndarray的数据类型。
例1.1.4,对以上函数的简单应用:
import numpy #导入numpy模块
a = numpy.zeros((3,3)) #生成3行3列元素全为0的矩阵
b = numpy.ones((3,1)) #生成元素全为1的数组
c = numpy.identity(4) #生成单位矩阵
d = numpy.empty((3,3)) #生成3行3列的空矩阵,元素值随机生成
e = numpy.linspace(0,6,7) #生成一个数组,各个元素在0、6之间等分
print('numpy.zeros((3,3)):\n',a)
print('numpy.ones((3,1)):\n',b)
print('numpy.identity(4):\n',c)
print('numpy.empty((3,3)):\n',d)
print('numpy.linspace(0,6,7):\n',e)
运行结果如下:
numpy.zeros((3,3)):
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
numpy.ones((3,1)):
[[1.]
[1.]
[1.]]
numpy.identity(4):
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
numpy.empty((3,3)):
[[0.00000000e+000 0.00000000e+000 0.00000000e+000]
[0.00000000e+000 0.00000000e+000 2.52961611e-321]
[8.34445137e-308 2.14321575e-312 9.28366228e-312]]
numpy.linspace(0,6,7):
[0. 1. 2. 3. 4. 5. 6.]
1.2 numpy数组属性
属性 | 说明 |
ndarray.ndim | 矩阵的秩,表维度的数量 |
ndarray.shape | 数组的维度,对于矩阵,n行m列 |
ndarray.size | 数组元素的总个数,相当于.shape中n*m的值 |
ndarray.dtype | ndarray对象的元素类型 |
ndarray.itemsize | ndarray对象中每个元素的大小,以字节为单位 |
ndarray.flags | ndarray对象的内存信息 |
ndarray.real | ndarray对象的实部 |
ndarray.imag | ndarray对象的虚部 |
ndarray.data | 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性 |
例1.2.1,numpy数组属性的使用:
import numpy as np #导入numpy模块,并用np代替
A = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print('矩阵的秩:',A.ndim) #求矩阵的秩
print('矩阵的行数和列数:',A.shape) #求矩阵的行数和列数
print('矩阵A:',A)
A.shape = (4,3) #ndarray.shape还可以用来调整数组的大小
print('调整后的矩阵A:',A)
print('元素的类型:',A.dtype) #求元素的类型
运行结果如下:
矩阵的秩: 2
矩阵的行数和列数: (3, 4)
矩阵A: [[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
调整后的矩阵A: [[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
元素的类型: int32
1.3 数组的索引和切片
通过对数组的索引和切片操作来实现对数组内容的访问和修改。对于一维数组来说,可以通过从0~n的下标进行索引,通过内置函数slice(),设置参数start、stop、step的值,切割出一个新的数组,也可以通过[start:stop:step]的方式来进行切片操作。
例1.3.1,一维数组的切片操作:
import numpy as np #导入numpy模块,并用np代替
a = np.array([1,2,3,4,5,6])
s1 = slice(1,5,2) #切片到stop结束,不包括stop处的值
print('s1:',a[s1])
b = a[1:5:1]
print('b:',b)
c = a[1::2] #省略stop
print('c:',c)
d = a[1:5] #省略step,默认为1
print('d:',d)
运行结果如下:
s1: [2 4]
b: [2 3 4 5]
c: [2 4 6]
d: [2 3 4 5]
多维数组的切片操作与一维数组的方法相同,此外,多维数组还可以通过使用省略号的方式来提取元素。
例1.3.2,多维数组的切片操作:
import numpy as np #导入numpy模块,并用np代替
A= np.array([[0,1,2,3],[4,5,6,7],[8,9,10,11]])
print('A:\n',A)
B = A[0,0:3] #对第1行进行切片和索引
print('对第1行进行切片和索引:\n',B)
C = A[::2] #对第1行和3行进行切片和索引
print('对第1行和3行进行切片和索引:\n',C)
D = A[::2,::2] #对第1行和3行进行切片和索引,在对第1行和3行中的元素分别切片和索引
print('对第1行和3行进行切片和索引,在对第1行和3行中的元素分别切片和索引:\n',D)
E = A[:,2] #对第3列元素切片索引
print('对第3列元素切片索引:\n',E)
F = A[...,2] #对第3列元素切片索引
print('对第3列元素切片索引:\n',F)
G = A[...,1:] #索引矩阵后3列元素
print('索引矩阵后3列元素:\n',G)
运行结果如下:
A:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
对第1行进行切片和索引:
[0 1 2]
对第1行和3行进行切片和索引:
[[ 0 1 2 3]
[ 8 9 10 11]]
对第1行和3行进行切片和索引,在对第1行和3行中的元素分别切片和索引:
[[ 0 2]
[ 8 10]]
对第3列元素切片索引:
[ 2 6 10]
对第3列元素切片索引:
[ 2 6 10]
索引矩阵后3列元素:
[[ 1 2 3]
[ 5 6 7]
[ 9 10 11]]
1.4 numpy数组运算
通过numpy包可以对数组进行一些运算,或对两个数组之间的元素进行对应操作。
例1.4.1,数组运算:
import numpy as np #导入numpy模块,并用np代替
a1 = np.array([3,4,5,6,7])
b1 = np.array([[1,2,3,4,5],[1,2,3,4,5]])
print('a1每个元素乘以3:\n',a1*3) #每个元素乘以3
print('a1每个元素除以3:\n',a1/3) #每个元素除以3
print('a1每个元素的平方:\n',a1**2) #每个元素的平方
print('a1每个元素+1:\n',a1+1) #每个元素+1
print('两个数组的元素相乘:\n',a1*b1) #两个数组的元素相乘
运行结果如下:
a1每个元素乘以3:
[ 9 12 15 18 21]
a1每个元素除以3:
[1. 1.33333333 1.66666667 2. 2.33333333]
a1每个元素的平方:
[ 9 16 25 36 49]
a1每个元素+1:
[4 5 6 7 8]
两个数组的元素相乘:
[[ 3 8 15 24 35]
[ 3 8 15 24 35]]
例1.4.2,数组的特殊运算:
import numpy as np #导入numpy模块,并用np代替
a = np.array([1,2,3,4,5,6,7,8,9])
a = a.reshape(3,3) #重新构造矩阵
print('重新构造矩阵:\n',a)
print('元素和:\n',a.sum())
print('最小元素:\n',a.min())
print('最大元素:\n',a.max())
print('行求和:\n',np.sum(a,axis=1))
print('列求和:\n',np.sum(a,axis=0))
print('行最小:\n',np.min(a,axis=1))
print('行最大:\n',np.max(a,axis=1))
运行结果如下:
重新构造矩阵:
[[1 2 3]
[4 5 6]
[7 8 9]]
元素和:
45
最小元素:
1
最大元素:
9
行求和:
[ 6 15 24]
列求和:
[12 15 18]
行最小:
[1 4 7]
行最大:
[3 6 9]
补充:
import numpy as np #导入numpy模块,并用np代替
a = np.array([1,2,3,4,5,6,7,8,9])
a = a.reshape(3,3) #重新构造矩阵
print('重新构造矩阵:\n',a)
#计算标准差和方差
print('数组的标准差:',a.std())
print('数组每列的标准差:',a.std(axis=0))
print('数组每行的标准差:',a.std(axis=1))
print('数组的方差:',a.var())
print('数组每列的方差:',a.var(axis=0))
print('数组每行的方差:',a.var(axis=1))
运行结果如下:
重新构造矩阵:
[[1 2 3]
[4 5 6]
[7 8 9]]
数组的标准差: 2.581988897471611
数组每列的标准差: [2.44948974 2.44948974 2.44948974]
数组每行的标准差: [0.81649658 0.81649658 0.81649658]
数组的方差: 6.666666666666667
数组每列的方差: [6. 6. 6.]
数组每行的方差: [0.66666667 0.66666667 0.66666667]
例1.4.3,转置与点积运算:
import numpy as np #导入numpy模块,并用np代替
c = np.array([[1,2,3,4,5,6],[1,2,3,4,5,6]])
print('未转置前:\n',c)
print('转置后:\n',c.T)
运行结果如下:
未转置前:
[[1 2 3 4 5 6]
[1 2 3 4 5 6]]
转置后:
[[1 1]
[2 2]
[3 3]
[4 4]
[5 5]
[6 6]]
在例1.4.3中,通过.T操作进行了数组的转置。在numpy包中还有一种函数也可以实现数组的转置,即numpy.transpose()函数。
numpy.transpose()函数语法格式如下:
numpy.transpose(arr,axes)
#参数说明如下:
#arr:表示要转置的数组;
#axes:表示整数列表,对应维度,在默认情况下所有维度都会进行转换。
例1.4.4,numpy.transpose()函数完成转置:
import numpy as np #导入numpy模块,并用np代替
c = np.array([[1,2,3,4,5,6],[1,2,3,4,5,6]])
print('转置后:\n',np.transpose(c))
运行结果如下:
转置后:
[[1 1]
[2 2]
[3 3]
[4 4]
[5 5]
[6 6]]
例1.4.3和例1.4.4观察,两者区别是,.T操作只能进行简单的轴对换,而numpy.transpose()函数还能对高维数组进行更加复杂的操作。
例1.4.5,数组元素的访问:(通常做数据处理时会用到)
import numpy as np #导入numpy模块,并用np代替
a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print(a)
print('访问第一行元素:\n',a[0])
print('访问第一行、第二行元素:\n',a[[0,1]])
print('访问第一行第二列元素:\n',a[0][1])
运行结果如下:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
访问第一行元素:
[1 2 3 4]
访问第一行、第二行元素:
[[1 2 3 4]
[5 6 7 8]]
访问第一行第二列元素:
2
例1.4.6,数组元素函数运算:
import numpy as np #导入numpy模块,并用np代替
a = np.array([[3,7,9,11],[4,6,8,10]])
print('a/2:\n',a/2)
print('向下取整:\n',np.floor(a/2))
print('向上取整:\n',np.ceil(a/2))
print('四舍五入:\n',np.round(a/2))
运行结果如下:
a/2:
[[1.5 3.5 4.5 5.5]
[2. 3. 4. 5. ]]
向下取整:
[[1. 3. 4. 5.]
[2. 3. 4. 5.]]
向上取整:
[[2. 4. 5. 6.]
[2. 3. 4. 5.]]
四舍五入:
[[2. 4. 4. 6.]
[2. 3. 4. 5.]]
1.5 随机数
随机数是机器学习中经常使用的内容。其中设置随机数种子,可以使用np.random.seed()函数,它可以保证在使用随机函数生成随机数时,随机数是可重复出现的;生成服从正态分布的随机数可以使用np.random.randn()函数;生成0~n整数的随机排序可以使用np.random.permutation()函数;生成服从均匀分布的随机数可以使用np.random.rand()函数;在指定范围生成随机数可以使用np.random.randint()函数。
对随机数种子的理解可以参考该博主的博文:
np.random.seed()随机数种子_程序员_Iverson的博客-CSDN博客
import numpy as np #导入numpy模块,并用np代替
#设置随机数种子
np.random.seed(11) #该参数值确定了生成随机数的顺序
#1、生成正态分布的随机数矩阵
a = np.random.randn(3,3)
print('生成正态分布的随机数矩阵:\n',a)
#2、将0~10之间的数进行随机排序
#设置随机数种子
np.random.seed(11) #该参数值确定了生成随机数的顺