Numpy是一个开源的Python科学计算库,是Python生态圈中最重要的底层支持库,支持快速的数组和矩阵运算。其官方网址为http://www.numpy.org/。
1.Numpy 基础
1.1 数组对象的特性
使用Numpy前,需要先引入Numpy库,标准格式为import numpy ,下文为了运用方便会以np代称
import numpy as np
创建第一个numpy数据:
import numpy as np
arr = np.arange(5) #生成一个含5个元素的数组
#生成的数组为 array([0,1,2,3,4])
使用type()函数查看生成的数组的数据类型
type(arr)
#输出
numpy.ndarray
ndarray为多维数组,是numpy中最为重要也是python进行科学计算非常重要和基本的数据类型。这类数组对象具有很多特性。以下介绍几个较为重要的特性:
- shape #数组的形状
shape属性是一个元组,表示数组的结构。比如一个二维的4*5数组shape为(4,5)
- ndim #数组的维度
ndim属性是int类型,需要用几个数字来表示才能唯一确定这个元素,这个数组就是几维
- size #数组中的元素个数
- dtype
- T
b = np.arange(6).reshape(2,3) #生成一个 2x3 的二维数组
#输出
array([[0,1,2],
[3,4,5]])
---------------------------------
b.shape
#输出
(2,3)
---------------------------------
b.ndim
#输出
2
---------------------------------
b.dtype
#输出
dtype('int32')
---------------------------------
b.T
#输出
array([[0,3],
[1,4],
[2,5]])
上面的例子调用np.arange()函数首先创建了一个含有个元素的一维数组,然后使用reshape()函数将其转换为2x3 的二维数组。
1.2 生成数组
Numpy 提供了多种生成数组的方法,可直接用元组、列表来生成数组,也可用内建的各种函数快速生成全0、全1的特殊数组,还可生成各类随机数数组。
1.使用array() 函数生成数组
可将元组、列表作为参数传递给array() 函数以生成Numpy数组
arr = np.array((1,2,3,4)) #以元组为参数生成数组
#输出
array([1,2,3,4)]
--------------------------------------------------
arr = np.array([10,20,30,40]) #以列表为参数生成数组
#输出
array([10,20,30,40])
--------------------------------------------------
#可用array()生成二维数组
arr = np.array([[1,2],[3,4],[5,6]]) #生成一个3x2 的二维数组
#输出
array([[1,2],
[3,4],
[5,6]])
2.使用arange() 函数生成数组
arange() 功能是生成指定范围内的等差数组。使用方法如下:
numpy.arange(start,stop,step,dtype=none)
你需要先设置值所在的区间 [开始, 停止),这是一个左开右闭区间。然后,再设置 step 步长用于设置值之间的间隔。最后的可选参数 dtype 可以设置返回 ndarray 的值类型。
np.arange(1,5) #生成 1 至 4 (不含终值5) 的数组,步长默认为 1
#输出
array([1,2,3,4])
-----------------------------------
np.arange(1,9,2) #步长为2,产生含1,3,5,7(不含终值9)的等差数组
#输出
array([1,3,5,7])
-----------------------------------
a=np.arange(1,4,0.5) #步长为0.5
#输出
array([1., 1.5, 2., 2.5, 3., 3.5])
a.dtype
#输出
dtype('float64')
#此时数据类型已默认改为浮点型
-----------------------------------
np.arange(4000).reshape(4,1000) #生成4x1000 的大数组,默认只显示周边元素
#输出
array([[ 0, 1, 2, ..., 997, 998, 999],
[1000, 1001, 1002, ..., 1997, 1998, 1999],
[2000, 2001, 2002, ..., 2997, 2998, 2999],
[3000, 3001, 3002, ..., 3997, 3998, 3999]])
3.使用ones()、zeros()、eye()等函数生成特殊数组
ones()函数会生成一个内容全为1的数组
numpy.ones(shape,dtype=None)
其中:
- shape 要生成数组的形状例如(3,3)生成3 x 3
- dtype 生成数组的数据类型
numpy.ones((3,3))
#输出
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
zeros()具体用法与上面的ones一致,zero生成全为0的特殊数组
numpy.zeros((2,3))
#输出
array([[0., 0., 0.],
[0., 0., 0.]])
eye()函数生成一个k对角线上为1其他为0的n x m 的数组
numpy.eye(n,m,k=0,dtype=None)
- n 生成数组的行数
- m 生成数组的列数
- k 对角线索引,默认为0(即主对角线) 正值为上对角线,负值为下对角线
numpy.eye(4,4)
#输出
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
----------------------------------
numpy.eye(4,4,k=1)
#输出
array([[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.],
[0., 0., 0., 0.]])
----------------------------------
numpy.eye(4,4,k=-1)
#输出
array([[0., 0., 0., 0.],
[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])
----------------------------------
numpy.eye(4,6)
#输出
array([[1., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0.],
[0., 0., 0., 1., 0., 0.]])
4.使用linspace()函数生成等差数组
linspace 方法也可以像 arange 方法一样,创建数值有规律的数组。linspace 用于在指定的区间内返回间隔均匀的值。需要指定等差数组的初值、终值和数据个数,但不需要指定差值,其方法如下:
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
- start:序列的起始值。
- stop:序列的结束值。
- num:生成的样本数。默认值为 50。
- endpoint:布尔值,如果为真,则最后一个样本包含在序列内。(默认包含终值即Ture)
- retstep:布尔值,如果为真,返回间距。
- dtype:数组的类型。
np.linspace(1,2,5)
#输出
array([1. , 1.25, 1.5 , 1.75, 2. ])
----------------------------------------------
np.linspace(-np.pi,np.pi,10) #在区间[-Π,+Π]内等间距生成10个数
#输出
array([-3.14159265, -2.44346095, -1.74532925, -1.04719755, -0.34906585,
0.34906585, 1.04719755, 1.74532925, 2.44346095, 3.14159265])
----------------------------------------------
np.linspace(1,2,5,endpoint=False) #不含终值
#输出
array([1. , 1.2, 1.4, 1.6, 1.8])
5.使用随机函数生成数组
Numpy 提供很多随机函数,都位于random模块中调用语法为“np.random.随机函数(参数)”
Python中的随机数都是按照一定算法生成的伪随机数。如果每次都先设置相同的随机数种子值seed,那么就能保证随机数按顺序生成的不变性。
函数名 | 函数描述 |
seed | 设置随机数种子 |
rand(d0,d1,...,dn) | 返回[0,1)间的符合均匀分布的随机小数数组 |
randn(d0,d1,...,dn) | 返回符合标准正态分布N(0,1) 的随机小数数组 |
randint(low,high,size) | 返回[low,high) 间的随机整数数组,size=(m,n)数组大小 |
random(size = (m,n)) | 返回[0,1)间的m x n 维度的随机小数数组 |
choice(a,n,replace=False/True) | 从数组a中随机选择n个数,选择是否可重复 |
normal(loc,scale,size) | 返回符合正态分布N(loc,scale^2)的随机数 |
uniform(low,high,size) | 产生指定区间均匀分布的样本值 |
np.random.rand(2) #返回区间[0,1)内的2个随机小数
#输出
array([0.56050779, 0.88779353])
--------------------------------------------------
np.random.random((2,4)) #返回2x3 二维随机小数数组
#输出
array([[0.68513579, 0.12350701, 0.15725728, 0.62919965],
[0.02551161, 0.59603107, 0.52135725, 0.73459657]])
--------------------------------------------------
np.random.randn(10) #返回10个标准正态分布N(0,1)随机数
#输出
array([-0.45582373, -0.12461931, 0.97664339, 0.39309304, -0.06248212,
0.8256254 , 1.01094441, -0.54147004, -0.55818899, 0.36409258])
--------------------------------------------------
np.random.randint(1,100,10) #返回区间[1,100)内的10个随机整数
#输出
array([57, 17, 35, 83, 65, 79, 1, 53, 57, 50])
--------------------------------------------------
np.random.randint(1,100,(2,3)) #返回区间[1,100)内的2x3的随机整数数组
#输出
array([[39, 48, 88],
[ 9, 86, 94]])
--------------------------------------------------
2.数组的运算和排序
2.1 数组和单个数据的运算
数组和单个数据的运算规则很简单,即对单个数据和数组的每个元素进行运算。Python 的列表一般需要编写循环代码才能对整个列表元素进行计算,而数组不需要循环语句就可实现同样的操作。
b = np.arange(5)
b
#输出
array([0,1,2,3,4])
--------------------------------------
b + 2 #将每个数组元素和单个数据相加
#输出
array([2,3,4,5,6])
--------------------------------------
b * 2 #将每个数组元素和单个数据相乘
#输出
array([0, 2, 4, 6, 8])
--------------------------------------
b / 2 #将每个数组元素和单个数据相除
#输出
array([0. , 0.5, 1. , 1.5, 2. ])
2.2 数组和数组的运算
1.数组形状相同时的运算
当两个数组的形状相同时,各位置上的元素对位计算。
a1 = np.arange(6).reshape(2,3)
a2 = np.arange(6).reshape(2,3)
array([[0, 1, 2],
[3, 4, 5]]) #a1,a2数组形状相同
----------------------------------------------------
a1 + a2 #数组加数组,各个元素对位相加
#输出
[[ 0 2 4]
[ 6 8 10]]
----------------------------------------------------
a1 * a2
#输出
[[ 0 1 4]
[ 9 16 25]]
----------------------------------------------------
a1 / a2
#输出
array([[nan, 1., 1.],
[ 1., 1., 1.]])
2.数组形状不同时的广播运算
当两个数组的形状不同时,Numpy将按照广播规则(broadcasting机制)进行运算。
broadcasting规则:
- 两个shape当中有一个为1就进行扩展
- shape中有位置缺失,也可进行扩展
- 结果数组的形状(shape)取各自运算数组的各个轴上的最大值
- 如果两个数组的形状在任何维度上均不匹配,且均没有等于1的维度,则无法进行运算并报错
a1 = np.arange(4) # a1是一维数组
array([0,1,2,3])
--------------------------------------------
a2 = np.arange(12).reshape(3,4) #a2是3x4的二维数组
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
--------------------------------------------
a1 + a2
#输出
array([[ 0, 2, 4, 6],
[ 4, 6, 8, 10],
[ 8, 10, 12, 14]])
上例中的a1 是一维数组,a2是3 x 4 的二维数组,两者的维数不同。a1的维数较小,Numpy在a1的维数前面加1补齐,可近似认为a1 的维数变为(1,4).现在a1 的第0维是1,a2 的第0维是3,Numpy将把a1的第0维补充为3,相当于将a1的维数变为(3,4),现在可将a1看作如下形状
a1:
array([[ 0, 1, 2, 3],
[ 0, 1, 2, 3],
[ 0, 1, 2, 3]])
再来展示一个(3,1)和(1,2)数组的广播运算示例
b1 = np.arange(3).reshape(3,1)
b2 = np.arange(10,12).reshape(1,2)
------------------------------------------
b1:
array([[0],
[1],
[2]])
------------------------------------------
b2:
array([[10, 11]])
------------------------------------------
b1 + b2
#输出
array([[10, 11],
[11, 12],
[12, 13]])
b1 的形状为(3,1),b2的形状为(1,2),两者都是二维数组,运算时无需增加维度,按照第三条规则,每个轴取最大值,因此结果数组形状为(3,2),则b1沿水平方向扩充为
b1:
array([[0,0 ],
[1,1 ],
[2,2 ]])
b2沿竖直方向扩充为
b2:
array([[10, 11 ],
[10, 11 ],
[10, 11 ]])
不满足广播规则的数组将无法进行运算。例如, 2x3和3x2 的两个数组无法计算,2x3和4x3的两个数组也无法广播计算,不符合第四条规则。
2.3 数组排序
Numpy 数组自带 sort() 排序方法,它可把数据从小到大排列。
np.random.seed(7) #设置随机数种子7,保证每次测试时按序生成相同的随机序列
b = np.random.randint(1,20,size=10) #生成区间[1,20)内的10个随机整数
b
#输出
array([16, 5, 4, 8, 15, 9, 15, 11, 9, 8])
--------------------------------------------------------------------
c = b.copy() #将数组b复制一份,用于后续的测试
b.sort() #排序后直接改变了b的数据顺序
b
#输出
array([ 4, 5, 8, 8, 9, 9, 11, 15, 15, 16])
如果排序时不想改变数组自身,那么可以使用np.sort() 函数
b = c.copy() #从备份数组c中恢复原数组
np.sort(b) #np.sort排序后返回一个新数组,数组b自身不变
#输出
array([ 4, 5, 8, 8, 9, 9, 11, 15, 15, 16])
还有一个常用的排序函数 np.argsort() 可以返回一个代表原数据顺序的有序下标数组
b
#输出
array([16, 5, 4, 8, 15, 9, 15, 11, 9, 8])
-------------------------------------------------
np.argsort(b) #排序后返回代表原数据顺序的有序下标
#输出
array([2, 1, 3, 9, 5, 8, 7, 4, 6, 0], dtype=int64)
argsort() 的排序结果表明数组b中最小的数是第2个,其次是第1个,最大的数是第0个
arg =np.argsort(b) #得到排序的有序下标数组
c = b[arg] #利用返回的下标数组抽取得到有序数组
c
#输出
array([ 4, 5, 8, 8, 9, 9, 11, 15, 15, 16])
----------------------------------------------------
b[arg[0]] #抽取最小的数
#输出
4
----------------------------------------------------
b[arg[-1]] #抽取最大的数
#输出
16