【数据挖掘与机器学习】二、Python编程基础(3):Numpy篇
开始学习前,先简单介绍一下Numpy
NumPy 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,也针对数组运算提供大量的数学函数库。在科学计算中,特别是在数据处理、机器学习等领域广泛使用。
创建数组
在numpy中的高效多维数组对象 ndarray中,数组中的元素是相同类型的,并且在内存中连续存储,这使得 NumPy 数组比传统的 Python 列表更节省空间并且访问速度更快。
numpy中有多种创建数组的方式,接下来将带大家一一介绍。
1.基于list或tuple创建数组
将列表和元组转为数组,并打印出来
import numpy as np
data1 = [1,3,5,7] #列表
w1 = np.array(data1)
print('w1:',w1)
data2 = (2,4,6,8) #元组
w2 = np.array(data2)
print('w2:',w2)
data3 = [[1,2,3,4],[5,6,7,8]] #多维数组
w3 = np.array(data3)
print('w3:',w3)
结果为:
w1: [1 3 5 7]
w2: [2 4 6 8]
w3: [[1 2 3 4]
[5 6 7 8]]
2.利用arrange创建数组
array1 = np.arange(10)
print('array1:',array1)
array2 = np.arange(0,1,0.2)
print('array2:',array2)
结果为:
array1: [0 1 2 3 4 5 6 7 8 9]
array2: [0. 0.2 0.4 0.6 0.8]
这样生成的数组是等差的,arrange的右边界的参数是不可取到的。
3.利用linspace和logspace函数创建数组
linspace的作用是生成等差数列,logspace的作用是生成对数等比数列。
array3= np.linspace(0,1,5)
array4 = np.logspace(0,1,5)
#生成1-10间的具有5个元素的等比数列
print('array3:',array3)
print('array4:',array4)
结果为:
array3: [0. 0.25 0.5 0.75 1. ]
array4: [ 1. 1.77827941 3.16227766 5.62341325 10. ]
4.zeros和ones函数创建数组
print('1维值为0的数组:',np.zeros(4))
print('3*3维值为0的数组:\n',np.zeros([3,3]))
print('1维值为0的数组:',np.ones(5))
print('2*3维值为0的数组:\n',np.ones([2,3]))
结果为:
1维值为0的数组: [0. 0. 0. 0.]
33维值为0的数组:
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
1维值为0的数组: [1. 1. 1. 1. 1.]
23维值为0的数组:
[[1. 1. 1.]
[1. 1. 1.]]
创建矩阵
print('对角阵:\n',np.diag([1,2,3,4]))
print('指定大小和数值的矩阵:\n',np.full((2,3),6))
运行结果如下:
对角阵:
[[1 0 0 0]
[0 2 0 0]
[0 0 3 0]
[0 0 0 4]]
指定大小和数值的矩阵:
[[6 6 6]
[6 6 6]]
数组属性的使用及类型转换。
warray=np.array([[1,2,3],[4,5,6]])
print('秩为:',warray.ndim)
print('形状为:',warray.shape)
print('元素的个数为:',warray.size)
warray.shape=3,2
print('设置shape后的数组:\n',warray)
print('原数组类型:',warray.dtype)
print('新数组类型:',warray.astype(np.float64).dtype)
结果为:
秩为: 2
形状为: (2, 3)
元素个数为: 6
设置shape后的数组:
[[1 2]
[3 4]
[5 6]]
原数组类型: int32
新数据类型 float64
生成随机数
通过np.random.rand()函数可以返回一个或一组服从“0~1”均匀分布的随机样本值。随机样本取值范围是[0,1),不包括1。
arr1 = np.random.randint(100,200,size = (2,4))
print('arr1:\n',arr1)
arr2 = np.random.rand(5)
print('arr2:\n',arr2)
arr3 = np.random.rand(3,2)
print('arr3:\n',arr3)
结果如下:
arr1:
[[124 181 162 136]
[167 162 109 195]]
arr2:
[0.30613952 0.47194935 0.33142581 0.26346133 0.78248995]
arr3:
[[0.0725466 0.94778127]
[0.68174658 0.20485257]
[0.86811148 0.11551568]]
改变数组维度
arr1 = np.arange(12)
print('arr1:\n',arr1)
arr2=arr1.reshape(3,4)
print('arr2:\n',arr2)
arr3 = arr1.reshape(2,-1)
print('arr3:\n',arr3)
结果如下:
arr1:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
arr2:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
arr3:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
数据散开和数据扁平化
ravel()函数和flatten()函数都是将多维数组转换为一维数组,区别在于ravel函数返回的是视图,会影响原始矩阵,flatten函数返回的是拷贝,不会影响原始矩阵。
arr1 = np.arange(12).reshape(3,4)
print('arr1:\n',arr1)
arr2 = arr1.ravel()
print('arr2:',arr2)
arr3 = arr1.flatten()
print('arr3:',arr3)
结果如下:
arr1:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
arr2: [ 0 1 2 3 4 5 6 7 8 9 10 11]
arr3: [ 0 1 2 3 4 5 6 7 8 9 10 11]
两个数组的组合与分割
1.利用hstack和vstack函数组合数组
hstack()这个函数会沿着水平轴(即列)将输入的数组堆叠起来。这意味着输出的数组的列数将是输入数组的列数之和,而行数将是输入数组中最大行数的值。
与之相对应,vstack()则用于按行堆叠(即在水平方向上堆叠)
如:
arr1: [0,1,2,3]
arr2: [4,5,6,7]
使用hstack()函数后,结果为[0,1,2,3,4,5,6,7]
使用vstack()函数后,结果为
[0,1,2,3]
[4,5,6,7]
下面通过代码举例:
arr1 = np.arange(6).reshape(3,2)
arr2 = arr1*2
arr3 = np.hstack((arr1,arr2))
print('横向合并:\n',arr3)
arr4 = np.vstack((arr1,arr2))
print('纵向合并:\n',arr4)
结果为:
横向合并:
[[ 0 1 0 2]
[ 2 3 4 6]
[ 4 5 8 10]]
纵向合并:
[[ 0 1]
[ 2 3]
[ 4 5]
[ 0 2]
[ 4 6]
[ 8 10]]
2.利用concatenate合并数组
其中axis是控制横向组合和纵向组合的参数
arr1 = np.arange(6).reshape(3,2)
arr2 = arr1*2
print('横向组合为:\n',np.concatenate((arr1,arr2),axis = 1))
print('纵向组合为:\n',np.concatenate((arr1,arr2),axis = 0))
结果为:
横向组合为:
[[ 0 1 0 2]
[ 2 3 4 6]
[ 4 5 8 10]]
纵向组合为:
[[ 0 1]
[ 2 3]
[ 4 5]
[ 0 2]
[ 4 6]
[ 8 10]]
数组的分割
arr = np.arange(16).reshape(4,4)
print('横向分割为:\n',np.hsplit(arr,2))
print('纵向组合为:\n',np.vsplit(arr,2))
结果为:
横向分割为:
[array([[ 0, 1],
[ 4, 5],
[ 8, 9],
[12, 13]]), array([[ 2, 3],
[ 6, 7],
[10, 11],
[14, 15]])]
纵向组合为:
[array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
[12, 13, 14, 15]])]
由此可见,若hsplit第二个参数为2,就是指在横向(行)上将数组一分为二,vsplit同理。
数组的转置与复制
我的理解是,对于二维数组,transpose(0,1)与原数组相同,其中y为0,x为1,所以transpose(1,0)即为x和y转置。更高维的理解也差不多是这样。
arr = np.arange(6).reshape(3,2)
print('矩阵:\n',arr)
print('转置矩阵:\n',arr.transpose((1,0)))
#复制
arr1 = arr[-4:-1].copy()
print(arr)
print(arr1)
结果为:
矩阵:
[[0 1]
[2 3]
[4 5]]
转置矩阵:
[[0 2 4]
[1 3 5]]
[0 1 2 3 4 5 6 7 8 9]
[6 7 8]
数组的索引
1.一维数组
arr = np.arange(10)
print(arr)
print(arr[2])#数组从下标0开始
print(arr[-1])#数组中最后一个数
print(arr[1:4])#不包含4是因为左闭右开
结果为:
[0 1 2 3 4 5 6 7 8 9]
2
9
[1 2 3]
2.多维数组
import numpy as np
arr = np.arange(12).reshape(3,4)
print(arr)
print(arr[0,1:3]) #索引第0行中第1列到第2列的元素
print(arr[:,2]) #索引第2列元素
print('索引结果1:',arr[(0,1),(1,3)])#索引位置在(0,1)和(1,3)的元素
#索引第1行中第0、2、3列的元素
print('索引结果2:',arr[1:2,(0,2,3)])
mask = np.array([1,0,1],dtype = np.bool)
#mask是一个布尔数组,它索引第0,2行中第1列元素
print('索引结果3:',arr[mask,1])
结果为:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[1 2]
[ 2 6 10]
索引结果1: [1 7]
索引结果2: [[4 6 7]]
索引结果3: [1 9]
数组元素的追加
a = [1,2,3]
b = []
for i in a:
b.append(i*i)
print('b数组:',b)
wy = np.array([1,2,3])
c = wy*2
print('c数组:',c)
结果为:
b数组: [1, 4, 9]
c数组: [2 4 6]
数组的运算
1.四则运算
x = np.array([1,2,3])
y = np.array([4,5,6])
print('数组相加结果:',x+y)
print('数组相减结果:',x-y)
print('数组相乘结果:',x*y)
print('数组幂运算结果:',x**y)
结果为:
数组相加结果: [5 7 9]
数组相减结果: [-3 -3 -3]
数组相乘结果: [ 4 10 18]
数组幂运算结果: [ 1 32 729]
2.比较运算
x = np.array([1,3,6])
y = np.array([2,3,4])
print('比较结果(<):',x<y)
print('比较结果(>):',x>y)
print('比较结果(==):',x==y)
print('比较结果(>=):',x>=y)
print('比较结果(!=):',x!=y)
结果为:
比较结果(<): [ True False False]
比较结果(>): [False False True]
比较结果(==): [False True False]
比较结果(>=): [False True True]
比较结果(!=): [ True False True]
3.条件逻辑运算
arr1 = np.array([1,3,5,7])
arr2 = np.array([2,4,6,8])
cond = np.array([True,False,True,False])
result = [(x if c else y)for x,y,c in zip(arr1,arr2,cond)]#若满足c条件,则x,否则y;x,y,c分别是数组arr1,arr2,cond中的元素
print(result)
结果为:
[1, 4, 5, 8]
ufunc函数的广播机制
广播(broadcasting)是指不同形状的数组之间执行算术运算的方式。举例说明。
arr1 = np.array([[0,0,0],[1,1,1],[2,2,2]])
arr2 = np.array([1,2,3])
print('arr1:\n',arr1)
print('arr2:\n',arr2)
print('arr1+arr2:\n',arr1+arr2)
结果为:
arr1:
[[0 0 0]
[1 1 1]
[2 2 2]]
arr2:
[1 2 3]
arr1+arr2:
[[1 2 3]
[2 3 4]
[3 4 5]]
where的基本用法
print(np.where([[True,False], [True,True]],[[1,2], [3,4]],[[9,8], [7,6]]))
#对于每个布尔值的位置,如果它是 True,那么 np.where() 将会从第二个数组 ([[1, 2], [3, 4]]) 中选取对应的元素;如果是 False,则从第三个数组 ([[9, 8], [7, 6]]) 中选取。
#对于 [True, False],将会得到 [1, 8](因为 True 对应 1,而 False 对应 8)。
#对于 [True, True],将会得到 [3, 4](两个 True 分别对应 3 和 4)。
w = np.array([2,5,6,3,10])
#当只提供一个条件表达式时,np.where 返回的是满足该条件的所有元素的索引。这些索引通常是以元组的形式返回,每个元素对应数组的一个轴。
print(np.where(w>4))
结果为:
[[1 8]
[3 4]]
(array([1, 2, 4], dtype=int64),)
排序
1.sort排序
arr = np.array([7,9,5,2,9,4,3,1,4,3])
print('原数组:',arr)
arr.sort()
print('排序后:',arr)
结果为:
原数组: [7 9 5 2 9 4 3 1 4 3]
排序后: [1 2 3 3 4 4 5 7 9 9]
2.带轴向参数的sort排序
arr = np.array([[4,2,9,5],[6,4,8,3],[1,6,2,4]])
print('原数组:\n',arr)
arr.sort(axis = 1) #沿横向排序
print('横向排序后:\n',arr)
结果为:
原数组:
[[4 2 9 5]
[6 4 8 3]
[1 6 2 4]]
横向排序后:
[[2 4 5 9]
[3 4 6 8]
[1 2 4 6]]
3.使用argsort和lexsort函数排序
arr = np.array([7,9,5,2,9,4,3,1,4,3])
print('原数组:',arr)
print('排序后:',arr.argsort())
#返回值为数组排序后的下标排列
a=[2,5,8,4,3,7,6]
b=[9,4,0,4,0,2,1]
c=np.lexsort((a,b))
print(c)
结果为:
原数组: [7 9 5 2 9 4 3 1 4 3]
排序后: [7 3 6 9 5 8 2 0 1 4]
[4 2 6 5 3 1 0]
lexsort函数当输入是一个矩阵时,默认排序最后一行的数据,前面的行都是辅助行。
数组内数据去重
names = np.array(['红色','蓝色','黄色','白色','红色'])
print('原数组:',names)
print('去重后的数组:',np.unique(names))
结果为:
原数组: [‘红色’ ‘蓝色’ ‘黄色’ ‘白色’ ‘红色’]
去重后的数组: [‘白色’ ‘红色’ ‘蓝色’ ‘黄色’]
实现数据重复
1.title函数实现
arr = np.arange(5)
print('原数组:',arr)
wy = np.tile(arr,3)
print('重复数据处理:\n',wy)
结果为:
原数组: [0 1 2 3 4]
重复数据处理:
[0 1 2 3 4 0 1 2 3 4 0 1 2 3 4]
2.repeat函数实现
import numpy as np
arr1 = np.arange(5)
print('原数组:',arr1)
w1 = np.tile(arr1,3)
print('原数组重复3次:\n',np.tile(arr1,3))
arr2 = np.array([[1,2,3],[4,5,6]])
print('重复数据处理:\n',arr2.repeat(2,axis=0))
结果为:
原数组: [0 1 2 3 4]
原数组重复3次:
[0 1 2 3 4 0 1 2 3 4 0 1 2 3 4]
重复数据处理:
[[1 2 3]
[1 2 3]
[4 5 6]
[4 5 6]]
axis=0表示纵向上的重复,为1表示横向上的重复
其他常用函数
arr = np.arange(20).reshape(4,5)
print('创建的数组:\n',arr)
print('数组的和:',np.sum(arr))
print('数组纵轴的和:',np.sum(arr,axis = 0))
print('数组横轴的和:',np.sum(arr,axis = 1))
print('数组的均值:',np.mean(arr))
print('数组横轴的均值:',np.mean(arr,axis = 1))
print('数组的标准差:',np.std(arr))
print('数组横轴的标准差:',np.std(arr,axis = 1))
结果为:
创建的数组:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
数组的和: 190
数组纵轴的和: [30 34 38 42 46]
数组横轴的和: [10 35 60 85]
数组的均值: 9.5
数组横轴的均值: [ 2. 7. 12. 17.]
数组的标准差: 5.766281297335398
数组横轴的标准差: [1.41421356 1.41421356 1.41421356 1.41421356]
总结
本节看似都是一些琐碎的知识点,但其中还是有很多值得深究的,如广播机制等在本节被一带而过,实际上是非常重要且需要理解的知识点,大家可以在网上学习相关内容。