目录
Numpy-Beginner
- 数组运算和矩阵运算是两个概念。数组运算指多数组对应元素分别独立运算,结果得到的数组和原数组形状相同,且有广播功能;矩阵运算是指标准的线性代数中的矩阵运算。numpy中绝大部分是数组运算。
- 区分维数和维度。维度是指每一维元素的个数;一维空间(直线)维数为1,二维空间(平面)维数为2,三维空间(立体)维数为3。
- 数组中含一层中括号的是一维数组(且为列方向排列),含两层的才是二维数组(内层为行方向,外为列方向)。
- 第三节Numpy基本运算和第九节常用函数有许多共同的东西,留意。
1. Numpy基本操作(2020.06.07)
import numpy as np
# 1.1 列表转为矩阵
array = np.array([
[1,3,5],
[4,6,9],
])
print (array)
# 1.2 显示数组维度维度
print ('number of dim:',array.ndim)
# 1.3 行数和列数()
print ('shape:',array.shape)
# 1.4 元素个数
print ('size:',array.size)
# 1.5 数组类型
print (type(array))
# 1.6 数组中元素的类型
print (array.dtype)
重要提示:
- 创建数组array()、求维度ndim、求形状shape、求元素个数size的用法。
- type(a)指的是数组a的类型,而非数组中元素的类型。a.dtype指的是数组中元素的类型。
2. Numpy创建array(2020.06.07)
import numpy as np
# 2.1 一维array创建
a = np.array([2,23,4],dtype = np.int32)# np.int默认为int32
print (a)
print (a.dtype)# 得到的是数组中元素的类型,而非数组的类型
# 2.2 多维array创建
a = np.array([
[2,3,4],
[3,4,5]
])# 2行3列
print (a)
#2.3 创建全0数组
a = np.zeros((3,4))# 括号中是全零数组的形状
print (a)
# 2.4 创建全1数组
a = np.ones((2,3),dtype = np.int)
print (a,a.dtype)
# 2.5 创建全空数组
# 其实每个值都是接近于0的数
a = np.empty((3,4))
print (a)
# 2.6 创建连续数组
a = np.arange(10,21,2)# 仍顾头不顾尾,10-20的数据,步长为2
print (a)# 一维
# 总结:区别于python创建列表用range,numpy中用arange
# 2.7 reshape操作
b = a.reshape((2,3))
print (b)
# 总结:若a中的元素不能恰好(不多也不少)构成2*3矩阵,则程序出错
# 2.8 创建连续型数据
a = np.linspace(1,10,20)# 顾头顾尾
print (a)
# 总结:以1位第一个元素,10位最后一位元素,在此间一共平均生成20个元素,一维
# 2.9 linspace的reshape操作
b = a.reshape((4,5))
print (b)
# 数组元素的数据类型即转换
# 2.10 创建浮点型类型的元素构成的数组,并查看数据类型
c = np.array([1,2,3,4],float)
print (c,c.dtype)
c = np.ones((2,3),dtype = 'float64')
print (c,c.dtype)
# 2.11 转换数据类型
c = c.astype(np.int64)
print (c.dtype)
c = np.array(['1','2','3','4'])
print (c,c.dtype)
c = c.astype(np.int)
print (c,c.dtype)
重要提示:
- python中的类型用type,numpy中的类型用dtype;python读写基于字符型,numpy默认int32。
- 创建全零数组np.zeros(),创建全1数组np.ones(),创建全空数组np.empty(),创建连续数组arange(起,终,步长),仍是顾头不顾尾(和python中for循环的range的区别仅在于名字不同。)
- 使用reshape时,重塑前的变量中的size若不能恰好构成重塑后的shape,则会出错。
- linspace(起,终,欲生成元素总数),顾头顾尾,在起终间平均生成指定元素个数。
- 创建各种元素类型的数组方法:在创建的数组后加 ,float64 或 ,dtype = 'float64’即可,例如a = np.ones((2,3),float64)。如果仅输入int或float,则int默认为32位,float默认64位。
- 数组中元素类型的转换用astype,例如a = a.astype(np.int)。字符串类型的数自也可以转为整型。
3. Numpy基本运算(2020.06.07)
import numpy as np
# 3.1 一维数组运算
a = np.array([10,20,30,40])
b = np.arange(4)# 生成0-3,步长为1的一维数组
print (a,b)
print (a-b)
print (a*b)
print (b**2)
print (np.sin(a))
print (b<2)# 返回布尔型
a = np.array([1,1,3,4])
b = np.arange(4)
print (a==b)
# 以上均为数组对应元素的操作,区别于线代中矩阵运算
print (a.dot(b))# 对应元素乘积再求和
# 3.2 多维数组运算
a = np.array([[1,1],[0,1]])
b = np.arange(4).reshape((2,2))
print (a,'\n')
print (b,'\n')
print (a.dot(b))
print (np.dot(a,b))# 与上行乘法一模一样,都是经典矩阵乘法,点乘
a = np.random.random((2,4))# 以0-1间的随机数生成2*4形状的数组
print ('a = ',a)
print (np.sum(a))
print (np.min(a))
print (np.max(a))
print ('每行sum =',np.sum(a,axis=1))
print ('每列min =',np.min(a,axis=0))
print ('每行max =',np.max(a,axis=1))
# 3.3 基本运算
a = np.arange(2,14).reshape((3,4))
print (a)
print (np.argmin(a))# 整个数组最小元素索引
print (np.argmax(a))
print (np.mean(a))# 整个数组的均值的三种方法
print (np.average(a))
print (a.mean())
print (np.median(a))# 中位数
print (np.cumsum(a))# 累加,每一索引上的元素改为该索引及其之前索引元素的和,
# 且将多维数组转化为1维数组。
b = np.array([
[3,5,9],
[4,8,10],
])
print (np.diff(b))# 累差,a*b形状数组元素每行的后一个元素减前一个元素的值,
# 得到a*(b-1)形状数组
c = np.array([[0,5,9],[4,0,10]])
print (np.nonzero(b))
print (np.nonzero(c))# 返回非零元素的位置,行位置存储在第一个列表,列位置存储在第二个列表
a = np.arange(14,2,-1).reshape((3,4))
print (a)# 步长为-1
print (np.sort(a))# np.sort(a,axis= )将数组a按每行(axis=1)或列中元素降序排列,
# 若不指定axis则默认按行降序
print (np.transpose(a))# 转置的两种求法
print (a.T)
print (np.clip(a,5,9))
'''clip(Array,Array_min,Array_max)
将Array_min<X<Array_max X表示矩阵A中的数,如果满足上述关系,则原数不变。
否则,如果X<Array_min,则将矩阵中X变为Array_min;
如果X>Array_max,则将矩阵中X变为Array_max.'''
print (a)# 说明以上变换均是临时性变换
# 常用函数
a = np.array([4,9,16])
print (np.sqrt(a))
print (np.abs(a))
print (np.square(a))
x = np.array([12,9,13,15])
y = np.array([11,10,4,8])
print (np.add(x,y))
print (np.multiply(x,y))
print (np.maximum(x,y))# 两组元素对应值比较,保留大的舍去小的,生成新数组
print (np.greater(x,y))# 两组元素对应值比较,x中元素大的位置为True,否则为False
重要提示:
- 区别数组和矩阵的运算方法,数组是对应元素分别计算,得到的结果是与原数组形状相同的数组;而矩阵是线性代数中的运算。
- np.arange(4)代表生成从0到3步长为1的数。
- a.dot(b)和np.dot(a,b)一模一样,表示经典矩阵乘法,即相乘再相加。区别于数组运算(±*/)矩阵运算没有除法。
- np.random.生成随机数组的一系列命令。np.random.random(a,b)表示以0-1间的随机数生成a*b形状的数组。
- sum(a,axis= )、max(a,axis= )、min(a,axis= ),当求数组全体的和、最大、最小元素时,省略axis项。或按每列(axis=0),每行(axis=1)
- 求整个数组最小元素索引np.argmin(a)。求整个数组元素的均值的三种方法np.mean(a)、np.average(a)、a.mean()。求整个数组中位数的方法np.median(a)
- 累加np.cumsum(a),每一索引上的元素改为该索引及其之前索引元素的和,且将多维数组转化为1维数组;累差np.diff(a),xy形状数组元素每行的后一个元素减前一个元素的值,得到x(y-1)形状数组。
- 返回数组中非零元素的位置print (np.nonzero©),非零元素的行位置存储在第一个列表,列位置存储在第二个列表。
- np.sort(a,axis= )将数组a按每行(axis=1)或列中元素降序排列,若不指定axis则默认按行降序。
- 转置的两种求法:np.transpose(a)或a.T 。
- clip(Array,Array_min,Array_max)
将Array_min<X<Array_max X表示矩阵A中的数,如果满足上述关系,则原数不变。
否则,如果X<Array_min,则将矩阵中X变为Array_min;
如果X>Array_max,则将矩阵中X变为Array_max. - 以上变换均是临时性变换,不影响a的状态。
- np.sqrt(a)开方、np.abs(a)绝对值、np.square(a)平方、np.add(a,b)相加、np.multiply(a,b)相乘、np.maximum(a,b)保留对应较大元素、np.greater(a,b)保留a中较大元素的布尔型。
4. Numpy索引与切片(2020.06.08)
import numpy as np
a = np.arange(3,15)
print (a)
print (a[3])# 一维数组的索引
print (a[3:7])
print (a[3:10:2])
b = a.reshape(3,4)
print (b)
print (b[2])# 打印第三行
print (b[0][2])# 打印第一行第三个元素
print (b[0,2])# 打印第一行第三个元素
print (b[:2])# 打印前两行元素
print (b[1,1:3])# 打印第1行的第2到3个元素,1:3表示1-2不包含3,顾头不顾尾
print (b[1:,1:])# 打印一个矩形区域
print (b[[0,2]])# 打印第一行,第三行
print (b[[0,2],[2,3]])# 打印索引为(0,2)(2,3)的元素
for row in b:
print (row)# 打印成多个一维数组
for column in b.T:
print (column)
a = np.arange(3,15,1).reshape(3,4)
print (a)
print (a.flatten())# 将多维数组转为一维,前提是numpy对象
for item in a.flat:# 注意此处是flat
print (item)
重要提示:
- 一维数组的某元素索引直接a[x]即可。
- 二维数组的某行所有元素的索引b[x];某个元素的索引b[x,y]或b[x][y];某行元素的切片b[x,y:z]表示x行中第y-1到第z-1元素,且顾头不顾尾。
- 按行打印为一维数组的方法,按列打印为一维数组的方法(转置),用for循环即可。
- a.flatten()将多维数组转为一维,前提是numpy对象。
- 从数组中取元素时,用[,]逗号前代表行的信息,逗号后代表列的信息。取元素有三种取发:1、取单个,2、取连续切片(可以设置步长),3、取多个指定元素(任意位置),方法见下图。
扩展:切片取值方式(对应颜色是取出来的结果):
5. Numpy array合并(2020.06.08)
import numpy as np
# 5.1 一维数组合并
a = np.array([1,1,1])
b = np.array([2,2,2])
c = np.vstack((a,b))# vertical stack上下合并为一个新二维数组
print (c)
print (a.shape,b.shape,c.shape)# (3,) (3,) (2, 3)
# 从shape中看出A,B均为拥有3项的一维数组(数列),按列排列
d = np.hstack((a,b))# 左右合并为一个一维数组(列)
print (d)
print (a.shape,b.shape,d.shape)# (3,) (3,) (6,)
# 5.2 一维数组转置为矩阵
# 对于A,B这种,一维数组或数列,无法进行转置,需要借助其他函数进行转置
print (a[np.newaxis,:])# 将一维列转为二维行,[1,1,1]转为[[1,1,1]]
print (a[np.newaxis,:].shape)# 将(3,)变为(1,3)
print (a[:,np.newaxis])# 将一维列转为二维列
print (a[:,np.newaxis].shape)# 将(3,)变为(3,1)
# 5.3 二维数组合并concatenate
a = a[:,np.newaxis]# 一维转二维
b = b[:,np.newaxis]
print (a)
print (b)
c = np.concatenate((a,b,b,a),axis = 0)# 纵向合并
print (c)
d = np.concatenate((a,b,b,a),axis = 1)# 横向合并
print (d)
# 5.4 合并二维数组例子
print ('\n')
a = np.arange(8).reshape(2,4)
b = np.arange(8,16).reshape(2,4)
c = np.concatenate((a,b),axis = 0)
d = np.concatenate((a,b),axis = 1)
print (c)
print (d)
重要提示:
- 一维数组实际是个数列,并非行。用print (np.array([1,1,1]))输出为(3,),表示三行一列。因为array中仅有一个中括号,中括号中的内容按列排列;若有两层中括号,则内层按行排列,外层按列排列。
- (3,)相似并不同于(3,1),(3,)的数组代表一维数组(列方向),仅有一个中括号;而(3,1)代表二维数组,只是第二维数组元素个数为1,有两层大括号.
- np.vstack(a,b,…)上下合并为一个新二维数组;np.hstack((a,b,…)) 左右合并为一个一维数组(列)。可合并多个数组,但仅处理一维数组。
- a[np.newaxis,:]将一维列转为二维行;a[:,np.newaxis]将一维列转为二维列。
- np.concatenate((a,b,b,a),axis = 0或1)可纵向或横向合并多个数组,处理二维数组的合并。区别于np.vstack()和np.hstack()。
6. Numpy array分割(2020.06.08)
import numpy as np
# 6.1 构造3行4列数组
a = np.arange(12).reshape(3,4)
print (a)
# 6.2 等量分割
# 纵向分割
print (np.split(a,2,axis = 1))# 括号中为待分割数组,分割份数,延哪个方向
# 横向分割
print (np.split(a,3,axis = 0))
# 6.3 不等量分割
print (np.array_split(a,3,axis = 1))
# 6.4 其他分割方式
# 横向分割
print (np.vsplit(a,3))# 等价于print(np.split(a,3,axis=0))
# 纵向分割
print (np.hsplit(a,2))# 等价于print(np.split(a,2,axis=1))
重要提示:
- 等量横向分割的两种方法:np.split(a,3,axis = 0)括号中为待分割数组,分割份数,延纵向元素个数分份数(然后横向切割)。等价于np.vsplit(a,3)
- 等量纵向分割的两种方法:np.split(a,2,axis = 1)括号中为待分割数组,分割份数,延横向元素个数分份数(然后纵向切割)。等价于np.hsplit(a,2)
- 不等量分割np.array_split(a,3,axis = 1)。
7. Numpy copy与=(2020.06.08)
import numpy as np
# 7.1 = 赋值方式会带来关联性
a = np.arange(4)
b = a
c = a
d = b
a[0] = 11# 很神奇,虽然修改a中元素在对bcd赋值之后,但bcd中的元素仍改变
print (a)
print (b)
print (c)
print (d)
print (b is a)
print (c is a)
print (d is a)# 感觉是abcd只是一个本体的多个名字而已
d[1:3] = [22,23]# 仍相关联
print (a)
print (b)
print (c)
print (d)
# 7.2 copy()赋值方式没有关联性
a = np.arange(4)
b = a.copy()# 很明显copy不是numpy包中的命令
print (a)
print (b)
a[3] = 44# a,b无关联
print (a)
print (b)
重要提示:
- 通过等号a = b传递的数组信息,各数组间的元素是关联的,一个数组变化,与之关联的也变化。而且不论是先通过等号赋值还是先修改其中一个数组中的元素,即与时间无关。
- 通过.copy()传递的信息是单向传递,传递完成后便为两个独立变量,没有关联性。一个数组信息的更改不影响另一个。
8. 广播机制(2020.06.08)
import numpy as np
# 8.1 数组间运算的广播
a = np.array([
[0,0,0],
[10,10,10],
[20,20,20],
[30,30,30],
])
b = np.array([0,1,2])
print (a+b)
# 为什么是这个样子?这里以tile模拟上述操作,来回到a.shape==b.shape情况!
# 对[0,1,2]行重复3次,列重复1次
b = np.tile([0,1,2],(4,1))
print (a+b)
# 8.2 数组与标量运算时,标量的广播
a = np.array([[1,2,3],[4,5,6]])
b = 10
print (a+b)
print (a-b)
print (a*b)
print (a/b)
重要提示:
- numpy数组间的基础运算是一对一,也就是a.shape==b.shape,但是当两者不一样的时候,就会自动触发广播机制。
- 并不是任何情况都可以触发广播,只有当两个数组的trailing dimensions compatible时才会触发广播,否则报错ValueError: frames are not aligned exception。上面表达意思是尾部维度必须兼容!也就是说:**欲触发广播,两数组的形状可以不同,但不能冲突!**例如2×3的和1×4的就不能。
- 虽(3,)实质形状是列排列的,但我们一般认为其是行排列,按行排列使用。
- 数组与标量间的运算,对标量作数组形状的广播即可。
扩展:可以触发广播的几种情况。
9. 常用函数(2020.06.08)
import numpy as np
# 9.1 np.bincount()
x = np.array([1,2,3,3,0,1,4])
print (np.bincount(x))# 记录数值01234出现的次数
# 9.2 np.argmax(a,axis=None)返回延轴axis最大值的索引
x = np.array([[1,3,3],[7,5,2]])
print (np.argmax(x))# 7最大,返回索引3(一个数,并非坐标),不设置axis默认全部数组
print (np.argmax(x,axis=0))# 求每列最大值对应索引,返回数组
print (np.argmax(x,axis=1))
x = np.array([1,3,2,3,0,1,0])
print (x.argmax())# 最大元素有重复时,返回第一个索引
# 9.4 求取精度
# 当decimals>=0时
print (np.around([-0.6,1.2798,2.357,9.67,13], decimals=0))
print (np.around([-0.67,1.365,3.248,13],decimals = 1))
# decimals表示保留的小数点后位数,around对各元素取绝对值后四舍五入,再恢复符号
# 当decimals<0时
print (np.around([1,2,5,6,56],decimals = -1))
print (np.around([4,5,59,68,159,160],decimals = -2))
# decimals表示对小数点前第几位进行处理(注意是处理而非保留),进行5舍6入
# 9.5 np.diff(x,axis=None)后一个元素减前一个元素
x = np.arange(1,16).reshape(3,5)
print (x,x.dtype)
print (np.diff(x,axis=1))# 默认为1,即按行
print (np.diff(x,axis=0))
# 9.6 取整(不进行四舍五入)
print (np.floor([-0.4,-0.5,-1.4,-1.5,-0.5,1.6,0.9]))# 向左
print (np.ceil([-0.4,-0.5,-1.4,-1.5,-0.5,1.6,0.9]))
# 9.7 np.where(条件,满足执行,不满足执行)
# np.where实现小于0的值用0填充吗,大于0的数不变!
x = np.array([[1,2,-2],[-2,0,1]])
print (x)
print (np.where(x>0,x,0))# 如果x>0则仍保留x,否则赋为0
x = np.arange(4)
y = np.arange(4,8)
z = np.array([True,False,True,True])
print (np.where(z,x,y))
# 9.8 np.any()存在,np.all()任意
a = np.array([
[1,-1,3],
[-6,9,7],
[0,-8,1],
])
print (np.any(a>0))
print (np.all(a))
# 9.9 唯一化即其他集合逻辑
a = np.array([12, 11, 34, 23, 12, 8, 11])
print (np.unique(a))# 唯一化并升序排列
print (np.in1d(a,[11,12]))# 将a中的值为11或12的位置标记为True,其余标False
# 注意上面的np.in1d()是数字1
重要提示:
- np.bincount(x)用法
- np.argmax(a,axis=None)返回延轴axis最大值的索引
- 求精度np.around([列表],decimals=None),当decimals>=0时表示保留小数点后的位数,遵循四舍五入;当decimals<0时,表示对小数点前第decimals处理,遵循五舍六入。
- np.diff(x,axis=None)后一个元素减前一个元素,结果会少一个维度;cf第三节numpy的基本运算np.cumsum累加和,结果并不会少维度。
- 向左向右取整:np.floor([列表]),np.ceil([列表])
- np.where(条件,满足条件执行的部分,不满足条件执行的部分)
- sort()排序,cf第三节基本运算。
- np.any()存在,np.all()任意,返回布尔型。
- np.unique(a)唯一化元素并升序排列;np.in1d(a,[11,12])标记指定元素为True,其余为False。
10. 随机数random模块(2020.06.11)
import numpy as np
print (np.random.rand(3,3))# rand生成一个在[0,1)范围内满足均匀分布的随机样本数
np.random.seed(0)# 随机因子,确定随机因子后无论运行多少次程序,得到的随机数总相同
np.random.seed(0)# 括号中代表编号,编号相同的本次程序中的所随机数相同,不同程序的随机数也相同
print (np.random.rand(5))# 随机生成包含5个元素的浮点数组
np.random.seed(0)
print (np.random.rand(5))# 发现生成的随机数仍与前行相同
np.random.seed()
print (np.random.rand(5))
print (np.random.randn(30))# 按正态分布生成30个随机数
重要提示:
- np.random.rand()生成一个在[0,1)范围内满足均匀分布的随机样本数。
- np.random.seed()生成随机因子及编号,确定随机因子后无论运行多少次程序,一次程序内、各次程序间,随机因子编号相同的产生的随机数总相同。seed仅对接下来的一次random生成随机数有效,即便是接下来有for循环,也只针对第一次循环有效。
- np.random.randn(30)根据正态分布生成30个数。