一、Python基础
1. 列表推导式与条件赋值
#在生成一个数字序列的时候,在 Python 中可以如下写出:
事实上可以利用列表推导式进行写法上的简化: [* for i in *]
。其中,第一个 *
为映射函数,其输入为后面 i
指代的内容,第二个 *
表示迭代的对象。
列表表达式还支持多层嵌套,如下面的例子中第一个 for
为外层循环,第二个为内层循环:
除了列表推导式,另一个实用的语法糖是带有 if
选择的条件赋值,其形式为 value = a if condition else b
:
下面举一个例子,截断列表中超过5的元素,即超过5的用5代替,小于5的保留原来的值:
2. 匿名函数与map方法
有一些函数的定义具有清晰简单的映射关系,例如上面的 my_func
函数,这时候可以用匿名函数的方法简洁地表示:
但上面的用法其实违背了“匿名”的含义,事实上它往往在无需多处调用的场合进行使用,例如上面列表推导式中的例子,用户不关心函数的名字,只关心这种映射的关系:
对于多个输入值的函数映射,可以通过追加迭代对象实现:
3. zip对象与enumerate方法
zip函数能够把多个可迭代对象打包成一个元组构成的可迭代对象,它返回了一个 zip
对象,通过 tuple, list
可以得到相应的打包结果:
往往会在循环迭代的时候使用到 zip
函数:
enumerate
是一种特殊的打包,它可以在迭代时绑定迭代元素的遍历序号:
用 zip
对象也能够简单地实现这个功能:
当需要对两个列表建立字典映射时,可以利用 zip
对象:
既然有了压缩函数,那么 Python
也提供了 *
操作符和 zip
联合使用来进行解压操作:
二、Numpy基础
1. np数组的构造
最一般的方法是通过 array
来构造:
下面讨论一些特殊数组的生成方式:
【a】等差序列:
np.linspace
# 起始、终止(包含)、样本个数
np.arange
# 起始、终止(不包含)、步长
【b】特殊矩阵: zeros, eye, full
【c】随机矩阵: np.random
最常用的随机生成函数为 rand, randn, randint, choice
,它们分别表示0-1均匀分布的随机数组、标准正态的随机数组、随机整数组和随机列表抽样:
对于服从区间 a 到 b 上的均匀分布可以如下生成:
一般的,可以选择已有的库函数:
randn
生成了 N(0,I) 的标准正态分布:
对于服从方差为 σ2 均值为 μ 的一元正态分布可以如下生成:
同样的,也可选择从已有函数生成:
randint
可以指定生成随机整数的最小值最大值(不包含)和维度大小:
choice
可以从给定的列表中,以一定概率和方式抽取结果,当不指定概率时为均匀采样,默认抽取方式为有放回抽样:
当返回的元素个数与原列表相同时,不放回抽样等价于使用 permutation
函数,即打散原列表:
2. np数组的变形与合并
【a】转置: T
【b】合并操作: r_, c_
对于二维数组而言, r_
和 c_
分别表示上下合并和左右合并:
一维数组和二维数组进行合并时,应当把其视作列向量,在长度匹配的情况下只能够使用左右合并的 c_
操作:
【c】维度变换: reshape
reshape
能够帮助用户把原数组按照新的维度重新排列。在使用时有两种模式,分别为 C
模式和 F
模式,分别以逐行和逐列的顺序进行填充读取。
特别地,由于被调用数组的大小是确定的, reshape 允许有一个维度存在空缺,此时只需填充-1即可:
下面将 n*1
大小的数组转为1维数组的操作是经常使用的:
3. np数组的切片与索引
数组的切片模式支持使用 slice
类型的 start:end:step
切片,还可以直接传入列表指定某个维度的索引进行切片:
此外,还可以利用 np.ix_
在对应的维度上使用布尔索引,但此时不能使用 slice
切片:
当数组维度为1维时,可以直接进行布尔索引,而无需 np.ix_
:
4. 常用函数
【a】 where
where
是一种条件函数,可以指定满足条件与不满足条件位置对应的填充值:
【b】 nonzero, argmax, argmin
这三个函数返回的都是索引, nonzero
返回非零数的索引, argmax, argmin
分别返回最大和最小数的索引:
【c】 any, all
any
指当序列至少 存在一个 True
或非零元素时返回 True
,否则返回 False
all
指当序列元素 全为 True
或非零元素时返回 True
,否则返回 False
【d】 cumprod, cumsum, diff
cumprod, cumsum
分别表示累乘和累加函数,返回同长度的数组, diff
表示和前一个元素做差,由于第一个元素为缺失值,因此在默认参数情况下,返回长度是原数组减1
【e】 统计函数
常用的统计函数包括 max, min, mean, median, std, var, sum, quantile
,其中分位数计算是全局方法,因此不能通过 array.quantile
的方法调用:
但是对于含有缺失值的数组,它们返回的结果也是缺失值,如果需要略过缺失值,必须使用 nan*
类型的函数,上述的几个统计函数都有对应的 nan*
函数。
对于协方差和相关系数分别可以利用 cov, corrcoef
如下计算:
最后,需要说明二维 Numpy
数组中统计函数的 axis
参数,它能够进行某一个维度下的统计特征计算,当 axis=0
时结果为列的统计指标,当 axis=1
时结果为行的统计指标:
5. 广播机制
广播机制用于处理两个不同维度数组之间的操作,这里只讨论不超过两维的数组广播机制。
【a】标量和数组的操作
当一个标量和数组进行运算时,标量会自动把大小扩充为数组大小,之后进行逐元素操作:
【b】二维数组之间的操作
当两个数组维度完全一致时,使用对应元素的操作,否则会报错,除非其中的某个数组的维度是 m×1 或者 1×n ,那么会扩充其具有 1 的维度为另一个数组对应维度的大小。例如, 1×2 数组和 3×2 数组做逐元素运算时会把第一个数组扩充为 3×2 ,扩充时的对应数值进行赋值。但是,需要注意的是,如果第一个数组的维度是 1×3 ,那么由于在第二维上的大小不匹配且不为 1 ,此时报错。
【c】一维数组与二维数组的操作
当一维数组 Ak 与二维数组 Bm,n 操作时,等价于把一维数组视作 A1,k 的二维数组,使用的广播法则与【b】中一致,当 k!=n 且 k,n 都不是 1 时报错。
6. 向量与矩阵的计算
【a】向量内积: dot
【b】向量范数和矩阵范数: np.linalg.norm
在矩阵范数的计算中,最重要的是 ord
参数,可选值如下:
ord | norm for matrices | norm for vectors |
None | Frobenius norm | 2-norm |
‘fro’ | Frobenius norm | – |
‘nuc’ | nuclear norm | – |
inf | max(sum(abs(x), axis=1)) | max(abs(x)) |
-inf | min(sum(abs(x), axis=1)) | min(abs(x)) |
0 | – | sum(x != 0) |
1 | max(sum(abs(x), axis=0)) | as below |
-1 | min(sum(abs(x), axis=0)) | as below |
2 | 2-norm (largest sing. value) | as below |
-2 | smallest singular value | as below |
other | – | sum(abs(x)**ord)**(1./ord) |
【c】矩阵乘法: @
三、练习
Ex1:利用列表推导式写矩阵乘法
一般的矩阵乘法根据公式,可以由三重循环写出:
Ex2:更新矩阵
设矩阵 Am×n ,现在对 A 中的每一个元素进行更新生成矩阵 B ,更新方法是 Bij=Aij∑k=1n1Aik ,例如下面的矩阵为 A ,则 B2,2=5×(14+15+16)=3712 ,请利用 Numpy
高效实现。
A=[123
456
789]
Ex3:卡方统计量
设矩阵 Am×n ,记 Bij=(∑i=1mAij)×(∑j=1nAij)∑i=1m∑j=1nAij ,定义卡方值如下:
χ2=∑i=1m∑j=1n(Aij−Bij)2Bij
请利用 Numpy
对给定的矩阵 A 计算 χ2 。