Datawhale提供的pandas学习的开源地址:Joyful Pandas
Pandas 预备知识
python基础
列表推导式与条件赋值
匿名函数与map方法
zip对象与enumerate方法
numpy基础
np数组构造
np数组变形与合并
np数组切片与索引
常用函数
广播机制
向量与矩阵的计算
练习
利用列表推导式写矩阵乘法
更新矩阵
卡方统计量
改进矩阵计算的性能
连续整数的最大长度
一、python基础
1.列表推导式与条件赋值
列表推导式:
[A for i in B] A为映射函数 i为指代的内容 B为迭代的对象
Ex:
单层嵌套
[my_func(i) for i in range(5)] my_func()自己定义的函数 i从0-4
多层嵌套
[m+’_’+n for m in [‘a’, ‘b’] for n in [‘c’, ‘d’] ] 其中m+’_’+n相当于自己定义的函数
条件赋值:
Value = a if condition else b:
Ex:
Value = ‘cat’ if 2>1 else ‘dog’
‘cat’
2.匿名函数与map方法
3.Zip对象与enumerate方法
enumerate 是一种特殊的打包,它可以在迭代时绑定迭代元素的遍历序号
L = list(‘abcd’)
For index, value in enumerate(L):
Print(index, value)
0 a
1 b
2 c
3 d
For index, value in zip(range(len(L)),L)
Print(index, print)
二、Numpy基础
1.Np数组的构造
np.array([1,2,3])
a.等差数列
np.linspace(1,5,11) #起始 终止(包含) 样本个数
np.arrange(1,5,2) #起始 终止(不包含) 步长
b.特殊矩阵
zeros,eye,full
np.zeros(2,3) 两行三列的零矩阵
np.eye(3) 3X3的单位矩阵
np.eye(3, k=1) 偏移主对角线一个单位的单位矩阵
np.full((2,3),10) 元组传入大小 10表示填充的数值
np.full((2,3),[1,2,3])
c.随机矩阵
np.random()
rand 表示0-1均匀分布的随机数组 np.random.rand(a, b)
randn 表示0-1均匀分布的标准正态的随机数组 np.random.randn(a, b)
randit 表示0-1均匀分布的随机整数组 np.random.randit( low, high,size) size=(a,b)
choice 表示0-1均匀分布的随即列表 np.random.choice(列表,(a,b)) choice 可以从给定的列表中,以一定概率和方式抽取结果,当不指定概率时为均匀采样,默认抽取方式为有
放回抽样:
my_list = ['a', 'b', 'c', 'd']
np.random.choice(my_list, 2, replace=False, p=[0.1, 0.7, 0.1 ,0.1])
array(['a', 'b'], dtype='<U1')
np.random.choice(my_list, (3,3))
array([['a', 'c', 'b'],
['b', 'b', 'd'],
['d', 'b', 'c']], dtype='<U1')
随机种子
固定随机数的输出结果
np.random.seed(0)
np.random.rand()
2.np数组的变形与合并
a.转置 T
np.zeros((2, 3)).T
b.数组的合并操作:r_ 上下合并 c_ 左右合并
np.r_[np.zeros((2,3)), zeros((2,3))]
np.c_[np.zeros((2,3)), zeros((2,3))]
一维数组和二维数组进行合并时,应当把其视作列向量,在长度匹配的情况下只能够使用左右合并的 c_ 操作。
c.维度变换:reshape
reshape 能够帮助用户把原数组按照新的维度重新排列。在使用时有两种模式,分别为 C 模式和 F 模式,分别以逐行和逐列的顺序进行填充读取
target = np.arange(8).reshape(2,4)
target.reshape((4,2), order='C') # 按照行读取和填充
target.reshape((4,2), order='F') # 按照列读取和填充
特别地,由于被调用数组的大小是确定的,reshape 允许有一个维度存在空缺,此时只需填充-1 即可:
target.reshape((4,-1))
下面将 n*1 大小的数组转为 1 维数组的操作是经常使用的:
target = np.ones((3,1))
target.reshape(-1)
3.np数组的切片与索引
数组的切片模式支持使用 slice 类型的 start🔚step 切片,还可以直接传入列表指定某个维度的索引进行切片:
target = np.arange(9).reshape(3,3)
target
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
target[:-1, [0,2]]
array([[0, 2],
[3, 5]])
np.ix_在对应的维度上使用布尔索引,但此时不能使用 slice 切片:
target[np.ix_([True, False, True], [True, False, True])]
array([[0, 2],
[6, 8]])
4.常用函数
a.where
where 是一种条件函数,可以指定满足条件与不满足条件位置对应的填充值
a = np.array([-1,1,-1,0])
np.where(a>0, a, 5) # 对应位置为 True 时填充 a 对应元素,否则填充 5
array([5, 1, 5, 5])
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 如下计算
aixs参数在二维Numpy数组统计中,他能够进行某一个维度下的统计特征计算,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.向量内积:a.dot(b)
b.向量范数和矩阵范数:np.linalg.norm
在矩阵范数的计算中,最重要的是 ord 参数,可选值如下
c. 矩阵乘法
三、练习(待补充)
Ex1:利用列表推导式写矩阵乘法
一般的矩阵乘法根据公式,可以由三重循环写出
M1 = np.random.rand(2,3)
M2 = np.random.rand(3,4)
res = [[sum(M1[i][k]*M2[k][j] for k in range(M1.shape[1]) for j in range(M2.shape[1]))]for i in range(M1.shape[0])]
Ex2:更新矩阵
这道题一开始自己做的时候没有用到前面的循环结构写代码如下:
import numpy as np
A = np.arange(1,10).reshape(3,-1)
B = np.array([A[i][j] * sum(1 / A[i][k] for k in range(A.shape[1])]for i in range(A.shape[0]) for j in range(A.shape[1]))
B.reshape(A.rhape)
print(B)
参考答案
A = np.arange(1,10).reshape(3,-1)
B = A*(1/A).sum(axis=1).reshape(-1,1)
B
参考答案跟我的答案就成了明显的对比。。。 这里我对参考答案的几个理解:
1.sum(axis=1) axis=0按列顺序 axis=1按行顺序 这里是要对行求和 所以axis=1
2.reshape(-1,1) 这里的reshape是对(1/A).sum(axis=1)进行重组 相当于把一个1X3的矩阵 变成一个3X1的矩阵 这也是我一开始看答案的误区 把reshape理解成了重组A*(1/A)。
Ex3:卡方统计量
np.random.seed(0)
A = np.random.randint(10, 20, (8, 5))
B = A.sum(0) * A.sum(1).reshape(-1,1) / A.sum()
B
res = ((A-B)**2 / B).sum()
res
做这题时候再一次加深了reshape的使用 不明白的小伙伴 可以单独去算一下A.sum(0)和A.sum(1) 再一次强调reshape是对A.sum(1)进行的 还有sum 一开始把res写出了 res = sum() 才发现生成的是一个按列求和的数组 应该使用 res=.sum()是对行跟列的求和。
Ex4:改进矩阵计算的性能
现有某人根据如下给定的样例数据计算 R 的值,请充分利用 Numpy 中的函数,基于此问题改进这段代码的性能。
np.random.seed(0)
m, n, p = 100, 80, 50
B = np.random.randint(0, 2, (m, p))
U = np.random.randint(0, 2, (p, n))
Z = np.random.randint(0, 2, (m, n))
def solution(B=B, U=U, Z=Z):
L_res = []
for i in range(m):
for j in range(n):
norm_value = ((B[i]-U[:,j])**2).sum()
L_res.append(norm_value*Z[i][j])
return sum(L_res)
solution(B, U, Z)
100566
(((B**2.sum(1).reshape(-1,1) + (U**2).sum(0) - 2*B@U).sum()
100566
Ex5:连续整数的最大长度
输入一个整数的 Numpy 数组,返回其中递增连续整数子数组的最大长度。例如,输入 [1,2,5,6,7],[5,6,7] 为具有最大长度的递增连续整数子数组,因此输出 3;输入 [3,2,1,2,3,4,6],[1,2,3,4] 为具有最大长度的递增连续整数子数组,因此输出 4。请充分利用 Numpy 的内置函数完成。 (提示:考虑使用 nonzero, diff 函数)
暂时没有思考明白看了一下参考答案
func = lambda x:np.diff(np.nonzero(np.r_[1,np.diff(x)!=1,1])).max()
func([1,2,5,6,7])
3
func([3,2,1,2,3,4,6])
4
最后感谢Datawhale大神们的答疑解惑!
肝!!!!