开始之前,请配置好python环境,同时检查是否安装了第三方库:numpy。
本文是博主的学习笔记,有不足之处还请指出。
1. 数据的维度
首先我们来了解一下基本概念。
1.1 什么是维度?
维度就是一组数据的组织形式。
1.2 一维数据
一维数据由对等关系的有序或无序数据构成,采用线性方式表示。即所有的数据都排列在同一方向上。如python中列表和集合的概念。
在python中可以通过如下方式来表示一维数据:
- 列表
- 集合
1.3 二维数组
二维数组有多个一维数据构成,是一维数据的组合形式。如表格、二维数组等。
- 二维列表
1.4 多维数据
多数据是基于一维和二维数据,从而在新维度上扩展形成。如在二维数据上在增加一个时间维度,这就变成了一个三维数据。
- 多维列表
1.5 高维数据
高维数据仅仅利用最基本的二元关系展示数据间的复杂结构。如复合型键值对。
- 字典
- josn
- XML
- YAML
2. NumPy的数组对象:ndarray
2.1NumPy是什么?
numpy是一个开源的、用于科学计算的基础的第三方库。
- numpy提供了一个强大的N维数组对象:ndarray
- 具有广播功能的函数
- 具有线性代数、傅里叶变换、随机数生成等功能
- NumPy是SciPy、pandas等数据处理或科学计算库的基础。
2.2 NUmPy的引入方式
一般的,我们习惯上运用如下方式来引用numpy库 :
import numpy as np
2.3 ndarray数组对象有什么用?
这里我们先借用代码来感觉其优势:
import numpy as np
# 求(a的三次方+b的二次方)
# 普通列表
a= [1,2,3,4,5,6,7,8,9]
b= [1,2,3,4,5,6,7,8,9]
c = list()
for i in range(len(a)):
c.append((a[i]**3 + b[i]**2))
print(c)
# numpy数组对象
c = np.array([1,2,3,4,5,6,7,8,9])
d = np.array([1,2,3,4,5,6,7,8,9])
e = c**3 + d**2
print(e)
通过以上代码可以发现,ndarray数组对象可以去掉元素间运算所需的循环,使一维向量更想单个数据,从而使使用者更专心于数据计算,而这仅仅是其中之一,下面让我们进一步了解numpy。
2.4 ndarray数组对象
ndarray是一个多维数组对象,由两部分构成:
- 实际数据
- 描述这些数据的元数据(数据维度、数据类型等)
此外,ndarray数组一般要求所有元素类型相同,数组下标从0开始。
想一想:数组与python中的列表有什么区别呢?
在程序中,ndarray的别名是array,因此我们可以使用np.array()来生成一个ndarray数组。需要注意的是,通过print()输出ndarray数组时,元素之间的分隔符不再是“,”,而是空格。
对于ndarray有两个基本的概念,轴和秩。
- 轴(axis):保存数据的维度,
- 秩(rank):轴的数量,即数据的维度。
ndarray对象的属性有如下几个:
- .adim:秩,即轴的数量或数据的维度
- .shape: ndarray对象的尺度
- .size:ndarray对象元素的个数
- .dtype:ndarray对象的元素类型
- .itemsize:ndarray对象中每个元素的大小,以字节为单位
import numpy as np
a = np.array([[1,2,3,4,5],[6,7,8,9,0]])
print(a.ndim)
print(a.shape)
print(a.size)
print(a.dtype)
print(a.itemsize)
结果如下:
2
(2, 5)
10
int32
4
2.5 ndarraay数组的创建和变换
创建ndarray的方法共有4种,具体如下:
(1)从python的列表、元组等类型中创建ndarray数组:
x = np.array(list/tuple,dtype=np.**)。
- 参数一:可以直接写入list/tuple,也可以将list/tuple传入其中
- 参数二:指定ndarray数组对象类型。当np.array()不指定dtype时,numpy将根据数据情况关联一个dtype类型。
import numpy as np
a = [[1,2,3],[4,5,6],[7,8,9]]
b = np.array(a)
print("间接传参方法:")
print(b)
print("直接传参方法:")
b = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(b)
print("列表、元组混合使用:")
b = np.array([[1,2,3],(4,5,6),[7,8,9]])
print(b)
输出如下:
间接传参方法:
[[1 2 3]
[4 5 6]
[7 8 9]]
直接传参方法:
[[1 2 3]
[4 5 6]
[7 8 9]]
列表、元组混合使用:
[[1 2 3]
[4 5 6]
[7 8 9]]
(2)使用numpy中的函数创建ndarray数组,如arange、ones和zeros等。
- np.arrange(low,high,step,dtype):类似range函数,返回ndarray类型
- np.ones(shape):根据指定的元组shape来创建一个全1的数组
- np.zeros(shape);根据指定的元组shape来创建一个全0的数组
- np.full(shape,val):根据指定的元组shape来创建一个全val的数组
- np.eye(n):创建一个n*n的正方形单位矩阵,对角线为1,其余为0
间接传参方法:
[[1 2 3]
[4 5 6]
[7 8 9]]
直接传参方法:
[[1 2 3]
[4 5 6]
[7 8 9]]
列表、元组混合使用:
[[1 2 3]
[4 5 6]
[7 8 9]]
输出如下:
使用arange:
[ 2 4 6 8 10 12 14 16 18]
使用ones:
[[1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1.]]
使用zeros:
[[0. 0. 0.]
[0. 0. 0.]]
使用full:
[[2 2 2 2]
[2 2 2 2]
[2 2 2 2]]
使用eye:
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 1. 0.]
[0. 0. 0. 1.]]
此外,numpy还提供了几个“模仿”样式的函数:
- np.ones_like(a)
- np.zeros_like(a)
- np.full_like(a,val)
三着分别是生成和a形状相同且元素为0/1/val的数组。
(3)使用numpy中其它函数创建ndarray数组 - np.linspace(low,hig h,num):根据起止数据等间距填充数据,其中num是生成元素的个数
- np.concatenate(a,b):将两个或多个数组合并,形成一个新的数组
import numpy as np
a = np.linspace(1,10,5)
b = np.linspace(1,20,5)
print("a:",a)
print("b:",b)
c = np.concatenate((a,b))
print("c",c)
输出为:
a: [ 1. 3.25 5.5 7.75 10. ]
b: [ 1. 5.75 10.5 15.25 20. ]
c [ 1. 3.25 5.5 7.75 10. 1. 5.75 10.5 15.25 20. ]
对创建后ndarray数组,可以对其进行维度变换和元素变换,这统称为ndarray数组的变换。常用的变换方法有如下几种:
- .reshape(shape): 返回一个由原元素构成的新的shape形状的数组,原数组不变
- .resize(shape): 功能同上,但修改原数组
- .swapaxes(ax1,ax2): 将两个数组的维度进行调换
- .flatten(): 对数组进行降维,原数组不变
- .tolist(): 转换成python中的列表
- .astype(): 对数组进行类型转换,返回一个新数组,原数组不变
import numpy as np
a = np.ones((2,3,4))
print("变换前的a:\n",a)
print("*"*50)
b = a.reshape((3,8))
print("经reshape变换后的a:\n",a)
print("经reshape变换后的的返回值:\n",b)
print("*"*50)
c = a.resize((3,8))
print("经resize变换后的a:\n",a)
print("经resize变换后的的返回值:\n",c)
print("*"*50)
a = np.ones((2,3,4))
print("变换前的a:\n",a)
d = a.flatten()
print("经flatten变换后的a:\n",a)
print("经flatten变换后的的返回值:\n",d)
print("*"*50)
输出为:
变换前的a:
[[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]]
**************************************************
经reshape变换后的a:
[[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]]
经reshape变换后的的返回值:
[[1. 1. 1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1. 1. 1.]]
**************************************************
经resize变换后的a:
[[1. 1. 1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1. 1. 1. 1.]]
经resize变换后的的返回值:
None
**************************************************
变换前的a:
[[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]]
经flatten变换后的a:
[[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]]
经flatten变换后的的返回值:
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
**************************************************
想一想:通过以上代码,你发现了什么?
2.6 ndarray数组的索引和切片
- 索引:获取数组中特定位置元素的过程
- 切片:获取数组元素子集的过程。
(1)一维数组的索引和切片
ndarray一维数组的索引和切片和python相同,这里通过代码进行解释;
import numpy as np
a = np.arange(1,8)
print("数组a为:",a)
# 取下标为3的元素
print("下标为3的元素:",a[3])
# 进行切片操作
print("切片:",a[0:4:2])
输出为:
数组a为: [1 2 3 4 5 6 7]
下标为3的元素: 4
切片: [1 3]
(2)二维及多维数组的索引和切片
二维数组的索引和切片其实就是一维数组的叠加。
import numpy as np
a = np.arange(24).reshape(2,3,4)
print(a)
print("取【1,2,1】:",a[1,2,1])
b = a[:,0:3:2,::2]
print("切片后:\n",b)
输出为:
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
取【1,2,1】: 21
切片后:
[[[ 0 2]
[ 8 10]]
[[12 14]
[20 22]]]
通过代码可以发现,实际上每个维度切片方法都与一维数组相同,即多个一维的叠加使用。
2.6 ndarray数组的运算
(1)标量运算:数组数组与标量(常量)的运算作用于数组的每一个元素。
import numpy as np
a = np.arange(1,10)
print("原数组为:",a)
print("c*4=",end="")
c = a*4
print(c)
输出如下:
原数组为: [1 2 3 4 5 6 7 8 9]
c*4=[ 4 8 12 16 20 24 28 32 36]
(2)一元函数运算
- np.abs(a):计算数组各元素的绝对值
- np.sqrt(a):计算数组各元素的平方根
- np.square(a):计算数组各元素的平方
- np.log(a)/np.log2(a)/np.log10(a):计算数组各元素的对数
- np.rint(a):计算数组各元素的四舍入值
- np.modf(a):分离元素的小数和整数部分,并以两个独立数组形式返回
- np.cos(a)
- np.sin(a)
- np.tan(a):计算三角函数
- np.cxp(a):计算各元素的指数值
- np.sign(a):计算各元素的符号值1(+),-1(-),0(0)
(3)二元函数运算 - ± * / **:基本运算
- np.fmax(a,b):元素级取最大
- np.fmin(a,b):元素级取最小
- np.mod(a,b): 元素级模运算
- np.copysign(a,b): 将y中元素符号赋给对应的a元素
- < > = !=等比较:元素级比较,产生Boolean值
3. numpy的随机数函数
numpy的随机数函数都存放在random子库中,其中一些常用的基础函数如下
- rand(d0,d1,d2,dn): 根据d0-dn创建随机数函数,元素范围为[0,1)的浮点数,且均匀分布
- randn(d0,d1,d2,dn): 根据d0-dn创建随机数函数,元素范围的浮点数,元素符合标准正态分布
- randint(low,[high,shape]): 根据shape创建一个范围在[low,high)之间的随机整数数组。
- sedd(s):随机数种子
import numpy as np
a = np.random.rand(3,4)
print("rand函数:\n",a)
b = np.random.randn(3,3)
print("randn函数:\n",b)
c = np.random.randint(10,50,(4,4))
print("randint函数:\n",c)
输出如下:
rand函数:
[[0.09798002 0.49921352 0.31738805 0.11513971]
[0.73888379 0.20517624 0.5653194 0.93201328]
[0.08834032 0.59798905 0.14361878 0.13311843]]
randn函数:
[[ 0.6802766 0.03696936 -0.3010713 ]
[-0.91815841 -2.38550783 1.28881925]
[-0.63961654 0.90820396 0.38482065]]
randint函数:
[[39 40 43 43]
[12 14 17 28]
[48 44 15 10]
[33 34 38 40]]
此外,部分常用的高级的随机数函数有:
- shuffle(a): 根据数组的第0轴进行随机排序,改变数组a
- permutation(a): 功能同上,但不改变原有数组,即返回一个新的数组
- choice(a,[size,replace,p]): 从一维数组a中以概率p抽取元素,形成size形状的新数组,replace表示可以重复使用元素(默认为False)
import numpy as np
a = np.random.randint(10,90,(4,5))
print("原有数组a:\n",a)
np.random.shuffle(a)
print("经shuffle变换后的a:\n",a)
print("_"*50)
a = np.random.randint(10,90,(4,5))
b = np.random.permutation(a)
print("经permutation变换后的a:\n",a)
print("经permutation变换后的a:\n",a)
print("经permutation变换后返回的值:\n",b)
print("_"*50)
a = np.arange(12)
print("原有一维数组:\n",a)
a = np.random.choice(a,(3,4),0.5)
print("变换后的数组:\n",a)
输出如下:
原有数组a:
[[64 34 56 55 26]
[33 72 14 56 16]
[55 45 26 43 71]
[27 21 34 19 22]]
经shuffle变换后的a:
[[33 72 14 56 16]
[64 34 56 55 26]
[55 45 26 43 71]
[27 21 34 19 22]]
__________________________________________________
经permutation变换后的a:
[[70 52 17 37 36]
[15 28 33 23 58]
[68 57 89 55 23]
[55 43 35 64 17]]
经permutation变换后的a:
[[70 52 17 37 36]
[15 28 33 23 58]
[68 57 89 55 23]
[55 43 35 64 17]]
经permutation变换后返回的值:
[[70 52 17 37 36]
[15 28 33 23 58]
[55 43 35 64 17]
[68 57 89 55 23]]
__________________________________________________
原有一维数组:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
变换后的数组:
[[ 2 1 8 10]
[11 0 7 11]
[ 1 7 1 7]]
最后,random还有一些关于分布的随机函数;
- uniform(low,high,size):均匀分布的数组
- normal(loc,scale,size): 正态分布的数组,loc为均值、scale为标准差,size为形状
- poisson(lam,size): 泊松分布的数组,lam为随机事件发生概率,size为形状
附:random中的统计函数:
- min()/max():最大最小值
- argmin()/argmax():计算a中元素最大最小值,降一维后的下标
- unuravel_index(index,shape):根据shape将一维下标转换成多维下标
- ptp():计算极差
- median():计算数组a中元素的中位数
4. numpy的统计函数
- sum(a,axis=None):根据给定轴axis计算数组a相关元素之和,axis整
数或元组 - mean(a,axis=None):根据给定轴axis计算数组a相关元素的期望,axis
整数或元组 - average(a,axis=None,weights=None):根据给定轴axis计算数组a相关元素的加权平均值
- std(a,axis=None):根据给定轴axis计算数组a相关元素的标准差
- var(a,axis=None):根据给定轴axis计算数组a相关元素的方差