NumPy
numpy的数据结构——ndarray(n维数组对象)。
1.1 创建数组
创建数组使用numpy的array
函数,
通过numpy,系统自带的列表list可以转换为numpy中的数组;
嵌套列表会被转换为一个多维数组(即,矩阵)。
注意:array数组内部的元素必须为相同类型,比如数值或字符串。(可以使用dtype查询其类型)
numpy的属性:
-
ndim
:维度 -
shape
:行数和列数 -
size
:元素个数关键字:
-
array
:创建数组 -
dtype
:指定数据类型 -
zeros
:创建数据全为0 -
ones
:创建数据全为1 -
full
:创建数据全为指定值,第二个参数就是指定值 -
empty
:创建数据接近0 -
arrange
:按指定范围创建数据(是python内置函数range的数组版) -
linspace
:创建线段numpy的一些数组创建函数:
示例:a=np.array([2,3,4],dtype=np.float) #用arange创建连续数据 a = np.arange(10,20,2) # 10-19 的数据,2步长 """ array([10, 12, 14, 16, 18]) """ #使用reshape改变数据形状 a = np.arange(12).reshape((3,4)) # 3行4列,0到11 """ array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) """ #用linspace创建线段型数据 a = np.linspace(1,10,20) # 开始端1,结束端10,且分割成20个数据,生成线段 """ array([ 1. , 1.47368421, 1.94736842, 2.42105263, 2.89473684, 3.36842105, 3.84210526, 4.31578947, 4.78947368, 5.26315789, 5.73684211, 6.21052632, 6.68421053, 7.15789474, 7.63157895, 8.10526316, 8.57894737, 9.05263158, 9.52631579, 10. ]) """
1.2 数据类型
dtype(数据类型)
通常只需要知道所处理的数据大致是浮点数、复数、整数、布尔值、字符串,还是普通的Python对象。
astype
:将一个数组从一个dtype转换成另一个dtype;
1.3 数组运算
数组的计算非常方便,不用大量的循环即可批量运算。
大小相等的数组之间的任何算术运算都会将运算应用到元素级。
数组与标量的算术运算会将标量值传播到各个元素。
大小相同的数组之间的比较会生成布尔值数组。
不同大小的数组之间的运算叫做广播。
c=a-b
c=a+b
c=a*b
c=b**2
c=10*np.sin(a) #sin函数
print(b<3) #在脚本中对print函数进行修改可以进行逻辑判断,返回一个bool类型的矩阵
X/2:除以2
X//2:整除2
对于多维数组的运算:
Numpy中的矩阵乘法分为两种:
-
对应元素相乘;
-
标准的矩阵乘法运算,即对应行乘对应列得到相应元素;
#第一种表示方法 c_dot=np.dot(a,b) #第二种表示方法 c_dot=a.dot(b)
#numpy.linalg中有一组标准的矩阵分解运算以及诸如求逆和行列式之类的东西。
-
sum()
-
min()
-
max()
-
argmin()
:求最小元素的索引; -
argmax()
:求最大元素的索引; -
mean()
:均值=average
-
median()
:中位数; -
cumsum()
:累加函数,生成的每一项矩阵元素均是从原矩阵首项累加到对应项的元素之后; -
diff()
:累差运算,每一行中后一项与前一项之差; -
nonzero()
:将所有非零元素的行与列坐标分隔开,重构成两个分别关于行和列的矩阵; -
sort()
:排序,多维数组可以在任何一个轴上进行排序,只需要将轴编号传给sort即可;顶级方法np.sort()返回的是数组的已排序副本,而就地排序则会修改数组本身。 -
transppose()
:转置,即np.transpose(A)=A.T,返回的是源数据的视图(不会进行任何复制操作)。可以用于计算矩阵的内积。 -
clip(Array,Array_min,Array_max)
:后面的最大最小值让函数判断矩阵中元素是否有比最小值小的或者比最大值大的元素,并将这些指定的元素转换为最小值或者最大值。 通用函数:快速的元素级数组函数
ufunc
是一种对ndarray中的数据执行元素级运算的函数。
如果需要对行或列进行查找运算,就需要在上述代码中为axis
进行赋值,axis=0
:以列作为查找单元;axis=1
:以行作为查找单元;
向量和矩阵的运算:
np.tile(v,(2,1))
:v是一个向量,后面的元组(2,1)表示,在行方向上堆叠2次,在列方向上堆叠1次。
逆矩阵:
np.linalg.inv(A)
:A的逆矩阵。
np.linalg.pinv(A)
:A的伪逆矩阵。
聚合运算:
np.prod()
:矩阵中元素的乘积;
np.percentile(big_array,q=50)
:百分数,选取位于50%的元素;
np.var()
:方差;
np.std()
:标准差;
np.partition(x,3)
:标定点,表示,3前面的数字都比3要小,3后面的数字都比3要大;
np.argpartition(x,3)
:输出索引;
Fancy Indexing:
1.4 数组转置和轴对换
转置是重塑的一种特殊形式,它返回的是源数据的视图(不会进行任何复制操作)。
-
transpose
方法; -
T
属性;对高维数组,transpose需要得到一个由轴编号组成的元组才能对这些轴进行转置:
这里,第一个轴被换成了第二个,第二个轴被换成了第一个,最后一个轴不变。
ndarray还有一个swapaxes
方法,需要接受一对轴编号:
从上面可以看出,两种方法的输出结果是相同的。
轴
即维度;对于二维数组,0轴——数组的行,1轴——数组的列;
对于三维数组,轴就有点复杂了;arr3d=np.arange(24).reshape((2,2,4)) #输出结果 array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7]], [[ 8, 9, 10, 11], [12, 13, 14, 15]]])
上面创建的三维数组(2,2,4),有3条轴,编号分别为0,1,2。
最好的观察办法就是先将三维数组降维成一个二维数组,这样就可以获得原数组的0轴、1轴。
把最内层数组作为一个整体来看待,即有:
A = [0, 1, 2, 3] B = [4, 5, 6, 7] C = [ 8, 9, 10, 11] D = [12, 13, 14, 15] arr = [[A, B], [C, D]]
通过这种变换,将原数组从形式上转化成了一个二位数组,但是注意这里的A、B、C、D均为一维数组,对它们进行操作时,要按照向量而非标量的运算法则进行。降维后的轴方向如下图:
可以通过对0、1轴方向求和验证。
那么关于2轴的方向:由于A、B、C、D均为一维数组,因此轴2即为最内层一维数组的行方向,如下图所示:
同样,可以对轴2求和验证。So,多维数组,numpy的对轴的编号是先行后列,由外向内!即(2,2,4)=(行,列,层)。三维示意图如下:
进行(1,0,2)转换,结果示意图:
#轴变换之前数组视图 array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7]], [[ 8, 9, 10, 11], [12, 13, 14, 15]]]) #进行(1,0,2)轴变换之后数组视图 array([[[ 0, 1, 2, 3], [ 8, 9, 10, 11]], [[ 4, 5, 6, 7], [12, 13, 14, 15]]])
进行(2,1,0)转换,结果示意图:
#轴变换之前数组视图 array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7]], [[ 8, 9, 10, 11], [12, 13, 14, 15]]]) #进行(2,1,0)轴变换之后数组视图 array([[[ 0, 8], [ 4, 12]], [[ 1, 9], [ 5, 13]], [[ 2, 10], [ 6, 14]], [[ 3, 11], [ 7, 15]]])
理解的过程中注意一点:轴变换的过程中,原点的字母A是不会离开原点的,哪几个轴变换动哪几个轴,没有涉及变换的轴,不需要改变。
例如进行(2,1,0)变换时,只有0轴和2轴变换,所以1轴不变,即A、B相对位置不改变;0轴和2轴对换,以A为例,需要将原先在2轴排列的一维数组搬到0轴上,原先0轴上排列的A、C,搬到2轴上。完成。
参考博客地址:[Numpy数组解惑][https://flat2010.github.io/2017/05/31/Numpy数组解惑]
transpose()函数接受的是一个由
轴编号
组成的有序元组,表示变换后的新组的轴编号顺序。
1.5 索引
一维索引
与元素列表或者数组中的表示方法类似;
注意:
- array[5:8]在这里不包括8这个位置,即不包括结尾。
- 跟列表最重要的区别在于,数组切片是原始数组的视图,数据不会被复制,视图上的任何修改都会直接反映到源数组上。【但是,某些情况下,你需要得到的是ndarray切片的一份副本而非视图,就需要明确地进行复制操作,例如
arr[5:8].copy()
。】
二维索引
可以利用:
对一定范围内的元素进行切片操作;
切片索引
切片是沿着一个轴向选取元素的;可以一次传入多个切片:
arr2d[:2,1:] #这样切片只能得到相同维数的数组视图,通过将整数和切片混合,可以得到低纬度的切片
布尔型索引
numpy.random.randn
:生成一些正态分布的随机数据;
要选择不等于某个值时,可以使用不等于符号(!=),也可以通过~
对条件进行否定。
花式索引
指利用整数数组进行索引;
花式索引跟切片不一样,它总是将数据复制到新数组中。
关于迭代输出的问题:
import numpy as np
A = np.arange(3,15).reshape((3,4))
print(A.flatten())
# array([3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
for item in A.flat:
print(item)
# 3
# 4
……
# 14
这一脚本中的flatten
是一个展开性质的函数,将多维的矩阵进行展开成1行的数列。而flat
是一个迭代器,本身是一个object属性。
1.6 array合并
对一个array
的合并,可以按行、列等多种方式进行合并。
np.vstack(A,B)
——可实现数组A、B的合并;vertical stack
本身属于一种上下合并,即对括号中的两个整体进行对应操作。
np.hstack(A,B)
——实现左右合并;
np.nexaxis()
:转置操作;
当A为一个序列时,可能无法实现A的转置,因为A不具备矩阵的属性,需要借助其他函数实现转置。
print(A[np.newaxis,:])
# [[1 1 1]]
print(A[np.newaxis,:].shape)
# (1,3)
print(A[:,np.newaxis])
"""
[[1]
[1]
[1]]
"""
print(A[:,np.newaxis].shape)
# (3,1)
np.concatenate((A,B,B,A),axis=1)
——针对多个矩阵或序列进行合并。其中axis
参数很好的控制了矩阵的纵向或是横向打印,相比较vstack
和hstack
函数显得更加方便。
列组合column_stack()
一维数组:按列方向组合
二维数组:同hstack一样
行组合row_stack()
以为数组:按行方向组合
二维数组:和vstack一样
第一种方式的容错性更好,当合并的对象维度不同时,第二种方式会报错。
1.7 唯一化以及其他的集合逻辑
针对一维ndarray的基本集合运算,最常用的可能就是np.unique
,用于找出数组中的唯一值并返回已排序的结果。
另一个函数np.inld
用于测试一个数组中的值在另一个数组中的成员资格,返回一个布尔型数组。
1.8 数组的文件输入输出
np.save
和np.load
是读写磁盘数组数据的两个主要函数
1.9 array分割
纵向分割:
A = np.arange(12).reshape((3, 4))
print(A)
"""
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
"""
print(np.split(A, 2, axis=1)) #A是要分割的矩阵,2是2等分,axis是沿轴1分割
"""
[array([[0, 1],
[4, 5],
[8, 9]]), array([[ 2, 3],
[ 6, 7],
[10, 11]])]
"""
#不支持不等分,会出错
横向分割:
print(np.split(A, 3, axis=0)) #3是3等分
# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8, 9, 10, 11]])]
不等量的分割:解决办法为np.array_split()
print(np.array_split(A, 3, axis=1))
"""
[array([[0, 1],
[4, 5],
[8, 9]]),
array([[ 2],
[ 6],
[10]]),
array([[ 3],
[ 7],
[11]])]
"""
其他分割方式:
print(np.vsplit(A, 3)) #等于 print(np.split(A, 3, axis=0))
# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8, 9, 10, 11]])]
print(np.hsplit(A, 2)) #等于 print(np.split(A, 2, axis=1))
"""
[array([[0, 1],
[4, 5],
[8, 9]]), array([[ 2, 3],
[ 6, 7],
[10, 11]])]
"""
B=np.arange(10)
np.split(B,[3,7])#表示从B[2]和B[6]处进行分割,分成3段
1.10 copy&deep copy
=的赋值方式会带有关联性
import numpy as np
a = np.arange(4)
# array([0, 1, 2, 3])
b = a
c = a
d = b
改变a
的第一个值,b
、c
、d
的第一个值也会同时改变。
a[0] = 11
print(a)
# array([11, 1, 2, 3])
确认b
、c
、d
是否与a
相同。
b is a # True
c is a # True
d is a # True
copy()的赋值方式没有关联性
b = a.copy() # deep copy
print(b) # array([11, 22, 33, 3])
a[3] = 44
print(a) # array([11, 22, 33, 44])
print(b) # array([11, 22, 33, 3])
此时a
与b
已经没有关联。
1.11 random模块
python random()
函数
random()
方法返回随机生成的一个实数,它在[0,1)范围内。
注意:random()
是不能直接访问的,需要到如random模块,通过random静态对象调用该方法。即,random.random()
。
上面的这个随机生成函数是没有参数的。
random()
函数中常见的函数如下:
random.seed(a=None,vesion=2)
:初始化随机数生成器;
random.randrange(stop)
/random.randrange(start,stop[,step])
:返回一个随机选择的元素;
random.randint(a,b)
:返回随机整数N,左右闭区间;
random.choice(seq)
:从非空序列seq返回一个随机元素;如下:[外链图片转存失败(img-aYmjrGkx-1566392799592)(assets/1565076759028.png)]
random.choices(population,weights=None,*,cum_weights=None,k=1)
:从population中选择替换,返回大小为k的元素列表。如果指定了weight序列,则根据相对权重进行选择。如果给出cum_weights序列,则根据累积权重进行选择。如果提供了权重序列,则它必须与population序列长度相同。
random.shuffle(x[,random])
:将序列x随机打乱位置;
random.sample(population,k)
:返回从总体序列或集合中选择的唯一元素的k长度列表。用于无重复的随机抽样。
random.random()
:返回0.0到1.0范围内的一个随机浮点数;
random.uniform(a,b)
:返回一个随机浮点数;
random.normalvariate(mu,sigma)
:正态分布,mu-平均值,sigma-标准差;
numpy.random模块:
numpy.random模块对Python内置的random进行了补充,增加了一些用于高效生成多种概率分布的样本值的函数。
np.random.normal(size=(4,4))
:生成标准正态分布的4x4样本数组;
np.random.seed(1234)
:确定随机数生成种子;
np.random.RandomState
:创建一个与其他隔离的随机数生成器;
permutation
:返回一个序列的随机排列或返回一个随机排列的范围;
shuffle
:对一个序列就地随机排列;
rand
:产生均匀分布的样本值;
randint
:从给定的上下限范围内随机选取整数;
randn
:产生正态分布(平均值为0,标准差为1)的样本值,类似于Matlab接口;
binomial
:产生二项分布的样本值;
normal
:产生正态分布的样本值;
beta
:产生Beta分布的样本值;
uniform
:产生在[0,1)中均匀分布的样本值。
np.random.randint()
:输出一个给定范围内的随机数;
np.random.randint(0,10)
#输出一个0~10之间的随机数
np.random.randint(0,10,size=10)
#输出的是一个向量(一个数组),含有10个元素,每个元素都是在0~10之间
np.random.randint(0,10,size=(3,5))
#传入一个元组,输出一个矩阵
np.random.seed(666)
:定义随机种子,方便下一次产生的随机数和上一次是相同的。
np.random.random()
:生成一个随机浮点数,在0~1之间;同样,可以传入一个size(可以是整数或元组)。
np.random.normal()
:生成一个正态分布的随机浮点数;