声明:本文环境为Windows10+jupyter notebook,请自行下载安装Anaconda
1、numpy库概述和安装
引言:
Python中用列表list保存一组值,可用来当做数组使用,由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针,未保存一个简单的[1,2,3],需要有3个指针和三个整数对象,对于数值计算来说这种结构显然比较浪费内存和CPU计算时间。
此外,Python还提供了一个array模块,array对象和列表不同,它直接保存数值,和C语言的一维数组有些类似,但是由于它不支持多维,也没有各种运算函数,因此也不适合做数值运算。
numpy的诞生弥补了这些不足,numpy提供ndarray(N-dimensional array object)对象:ndarray是存储单一数据类型的多维数组。
numpy(Numerical Python的简称)是高性能科学计算和数据分析的基础包,支持维度数组与矩阵运算。包括:
(1)一个强大的N维数组对象ndarray,具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。
(2)用于对整组数据隐形快速运算的标准数学函数(无需编写循环)。
(3)用于读写磁盘数据的工具以及用于操作内存映射文件的工具。
(4)线性代数、随机数生成以及傅里叶变换等功能。
(5)用于继承C、C++、Fortran等语言编写的代码的工具
numpy库提供了大量的库函数和操作,可以帮助程序猿轻松的进行数值计算,这类数值广泛用于以下任务:
(1)机器学习模型:在编写机器学习算法时,需要对矩阵进行各种数值计算。例如矩阵乘法加法等,使用numpy库可进行简单和快速计算。numpy数组用于存储训练数据和机器学期模型的参数。
(2)图像处理和计算机图形学:计算机中的图形表示为多维数字数组,numpy提供了一些优秀的库函数来快速处理图像。例如镜像图像、按特定角度旋转图像等。
(3)数学任务:numpy可进行数值积分、微分、内插、外推等操作。numpy库形成了一种基于Python的MATLAB的快速替代。
安装:
安装numpy最简单的方法,pip工具代码如下:
--user选项表示只安装在当前用户下,不是写到系统目录中。
python -m pip install --user numpy
2、numpy数组操作
【ndarray概述】
》N维数组对象ndarray适用于存放同类型元素的多维数组。
》ndarray中的每个元素在内存中都有相同存储大小的区域。
》ndarray中的每个元素是数据类型对象的对象(称为dtype)。
》与Python中的其他容器对象一样,可以通过对数组进行索引或切片。
》可通过ndarray的方法和属性来访问和修改ndarray的内容。
ndarray之创建数组:
最简单的方法是使用array函数。它接受一切序列型的对象,然后产生一个含有传入数据的numpy数组。其中,嵌套序列将会被转换为一个多维数组。
numpy.array(object,dtype=None,copy=True,order=None,subok=False,ndmin=0)
名称 | 描述 |
---|---|
object | 数组或嵌套的数列 |
dtype | 数组元素的数据类型,可选 |
copy | 对象是否需要复制,可选 |
order | 创建数组的样式,C为行方向,F为列方向,A为任意方向 |
subok | 默认返回一个与基类类型一致的数组 |
ndin | 指定生成数组的最小维度 |
>> import numpy as np
>> a=[1,2,3,4] # 创建简单的列表
>> b=np.array(a) # 将列表转换为数组
>> b
array([1,2,3,4])
>> c=np.array([[1,2],[3,4]])
>> print(c)
[[1 2]
[3 4]]
除了np.array之外,还有一些函数也可以新建数组:
> zeros和ones分别可以用于创建指定长度或者形状的全0或全1数组。> empty可以创建一个没有任何具体值的数组。
>> import numpy as np
>> np.zeros(3) # 全0一维数组
array([0.,0.,0.])
>> np.ones(3) # 全1一维数组
array([1.,1.,1.])
>> np.zeros((3,3)) # 全0二维数组,3行3列
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
>> np.ones((3,3)) # 全1二维数组,3行1列
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
>> np.identity(3) # 单位矩阵,3行3列
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
【创建随机数组】
>> np.random.rand(5,5) # 创建指定形状的数组,范围在0至1之间
array([[0.18958258, 0.99081753, 0.94536359, 0.50506502, 0.30719297],
[0.87369297, 0.45526996, 0.36816989, 0.95841558, 0.2649228 ],
[0.49620817, 0.53016646, 0.36794172, 0.21930886, 0.20047452],
[0.2816989 , 0.11543322, 0.52197946, 0.75586478, 0.21387594],
[0.33406605, 0.09586188, 0.51795042, 0.73277065, 0.32744227]])
>> np.random.uniform(0,100) # 创建指定范围内的一个数
26.259620386892358
>> np.random.randint(0,100) # 创建指定范围内的一个整数
62
>> np.random.normal(1.75,0.1,(2,3)) # 给定均值/标准差/维度的正态分布
array([[1.5979596 , 1.94714557, 1.699023 ],
[1.83694804, 1.69616237, 1.76031946]])
>> np.random.randint(0,50,5) # 随机数组,5个0到50之间的数字
array([12, 5, 7, 4, 22])
>>np.random.standard_normal(5) # 从标准正态分布中随即采样5个数字
array([-0.95519789, -1.06259055, -0.34076133, 0.65119027, -0.31220016])
ndarray之数组属性 :
用法 | 说明 |
---|---|
b.size | 数组元素个数 |
b.shape | 数组形状 |
b.ndim | 数组维度 |
b.dtype | 数组元素类型 |
b.itemsize | 数组元素字节大小 |
# 数组属性
import numpy as np
x = np.array([(1,2,3),(4,5,6)])
print(x)
print(x.size)
print(x.ndim)
print(x.shape)
print(x.itemsize)
print(x.dtype,'\n')
y = x.reshape(3,2)
print(y)
print(y.shape)
输出结果:
[[1 2 3]
[4 5 6]]
6
2
(2, 3)
4
int32
[[1 2]
[3 4]
[5 6]]
(3, 2)
数组和标量之间的运算:
> 数组很重要,因为他可以使我们不用编写循环即可对数据执行批量运算。这通常叫做矢量化(vectorization)。大小相等的数组之间的任何算术运算都会将运算应用到元素级。同样,数组与标量的算数运算也会将那个标量值传播到每个元素。
>> import numpy as np
>> arr = np.array([[1.,2.,3.],[4.,5.,6.]])
>> arr
array([[1., 2., 3.],
[4., 5., 6.]])
>> 1/arr
array([[1. , 0.5 , 0.33333333],
[0.25 , 0.2 , 0.16666667]])
>> arr - arr
array([[0., 0., 0.],
[0., 0., 0.]])
>> arr*arr
array([[ 1., 4., 9.],
[16., 25., 36.]])
>> arr**0.5
array([[1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974]])
【基本的索引和切片】
> 选取数据子集或单个元素的方式有很多
> 一维数组很简单,从表面上看,他们跟Python列表的功能差不多。
> 一维数组跟列表最重要的区别在于,数组切片是原始数组的视图,这意味着数据不会被复制,数组视图上的任何修改都会直接反应到原始数组上。
> 将一个标量值赋值给一个切片时,该值会自动传播到整个选区。
>> import numpy as np
>> arr = np.arange(10)
>> print(arr)
[0 1 2 3 4 5 6 7 8 9]
>> arr[5] # 取索引为5的值
5
>> arr[5:8] # 取索引为[5,8)这个区间的值
array([5, 6, 7])
>> arr[5:8] = 12 # 将索引为5~8的元素修改为12
>> arr
array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
>> arr_slice = arr[5:8] # 将arr数组5~8的元素作为新数组的元素
>> arr_slice[1] =12345 # 将新数组的索引为1的元素修改为12345
>> arr
array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8,
9])
>> arr_slice[:] = 64
>> arr
array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])
> 在二维数组中,各索引位置上的元素不再是标量而是一维数组
> 还可以对各个元素进行递归访问,但是有点麻烦
> 还有一种方式是传入一个以逗号隔开的索引来选取单个元素
> 在多维数组中,如果省略了后面的索引,则返回对象会是一个维度低一点的ndarray
>> import numpy as np
>> arr3d = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]) # 两个二维数组组成的三维数组
>> arr3d
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
>> arr3d[0] # 取三维数组的索引为0的元素,即第一个二维数组
array([[1, 2, 3],
[4, 5, 6]])
>> arr3d[0][1] # 按索引取第一个二维数组的第二个一维数组
array([4, 5, 6])
【数学和统计方法】
基本数组统计方法:可以通过数组上的一组数学函数对整个数组或某个轴向的数据进行计算
方法 | 说明 |
---|---|
sum | 对数组中全部或某轴向的元素求和。零长度的数组sum为0 |
mean | 算数平均数。零长度的数组mean为NaN |
std,var | 分别为标准差和方差,自由度可调(默认为n) |
min,max | 最大值和最小值 |
argmin,argmax | 最大和最小元素的索引 |
cumsum | 所有元素的累加 |
cumprod | 所有元素的累积 |
> sum、mean以及标准差std等聚合计算既可以当做数组的实例方法调用,也可以当做项级numpy函数使用。
>> import numpy as np
>> arr = np.random.randn(5,4) # 5行4列正太分布的数据
>> print(arr)
>> print(arr.mean(),'\n') # 实例方法调用
>> print(np.mean(arr),'\n')
>> print(arr.sum(),'\n')
运行结果:
[[ 1.00337894 -0.58464469 0.52354766 -0.9112032 ]
[ 0.39131326 0.26497808 0.50512501 0.23437021]
[-0.86304844 0.47144653 0.7895093 -0.37087672]
[ 1.2245063 -0.10109734 -1.47588426 -1.03102073]
[ 0.02636393 -0.96448101 -0.34462713 -0.24302158]]
-0.07276829372562879
-0.07276829372562879
-1.455365874512576
> mean和sum这类的函数可以接受一个axis参数(用于计算该轴向上的统计值)
>> print(arr.mean(axis=0),'\n') # 按列求平均值
[ 0.3565028 -0.18275968 -0.00046589 -0.4643504 ]
>> print(arr.mean(axis=1),'\n') # 按行求平均值
[ 0.00776968 0.34894664 0.00675767 -0.34587401 -0.38144145]
我们来看整个示例:
import numpy as np
arr = np.random.randn(5,4) # 5行4列正太分布的数据
print(arr)
print(arr.mean(),'\n') # 实例方法调用
print(np.mean(arr),'\n')
print(arr.sum(),'\n')
print(arr.mean(axis=0),'\n') # 按列求平均值
print(arr.mean(axis=1),'\n') # 按行求平均值
print(arr.sum(0),'\n')
print(arr.sum(1),'\n')
b = np.array(arr[0])
print(arr[0])
print(b.mean()) # 验证第一行平均值
运行结果并验证:
[[ 1.00337894 -0.58464469 0.52354766 -0.9112032 ]
[ 0.39131326 0.26497808 0.50512501 0.23437021]
[-0.86304844 0.47144653 0.7895093 -0.37087672]
[ 1.2245063 -0.10109734 -1.47588426 -1.03102073]
[ 0.02636393 -0.96448101 -0.34462713 -0.24302158]]
-0.07276829372562879
-0.07276829372562879
-1.455365874512576
[ 0.3565028 -0.18275968 -0.00046589 -0.4643504 ]
[ 0.00776968 0.34894664 0.00675767 -0.34587401 -0.38144145]
[ 1.78251399 -0.91379842 -0.00232943 -2.32175202]
[ 0.03107872 1.39578656 0.02703067 -1.38349603 -1.52576578]
[ 1.00337894 -0.58464469 0.52354766 -0.9112032 ]
0.007769678803297209
> cumsum:按照所给定的轴参数返回元素的梯形累计和,axis=0,按照行累加。axis=1,按照列累加
> cumprod:按照所给定的轴参数返回元素的梯形累积乘积,axis=0,按照行累积。axis=1,按照列累积。
import numpy as np
arr = np.array([[0,1,2],[3,4,5],[6,7,8]])
print(arr)
print(arr.cumsum(0)) # 按行求累加
print(arr.cumprod(1)) # 按列求累积
运行结果:
[[0 1 2]
[3 4 5]
[6 7 8]]
[[ 0 1 2]
[ 3 5 7]
[ 9 12 15]]
[[ 0 0 0]
[ 3 12 60]
[ 6 42 336]]
最后一个需要说明一下:按行求累加为按照包括当前行在内的所以前面的行求累加,按列求累积为包括当前列在内的所有前面的列的累积。
只有小白最懂小白需要什么,多实践,对照代码理解,加油。