Data Whale第20期组队学习 Pandas学习—预备知识

一、Python基础

1.1 列表推导式和条件赋值

使用以下代码生成一个数字序列:

num=[]
def my_function(x):
    return x**3
for i in range(5):
    num.append(my_function(i))
print("num=",num)
# num= [0, 1, 8, 27, 64]
print("num=",[my_function(i) for i in range(5)])# 简化写法
# num= [0, 1, 8, 27, 64]

# 列表表达式还支持多层嵌套
print([i+'+'+j for i in['a','b'] for j in ['c','d']])#第一个 for 为外层循环,第二个for为内层循环
# ['a+c', 'a+d', 'b+c', 'b+d']

# 带有 if 选择的条件赋值
animal='cat' if 5>4 else 'dog'
print("animal=",animal)
# animal= cat

# 截断列表中超过10的元素,即超过10的用20代替,小于10的保留原来的值:
num1=[]
for j in range(5,15):
    num1.append(j)
print([k if k<=10 else 20 for k in num1])
#[5, 6, 7, 8, 9, 10, 20, 20, 20, 20]

1.2 匿名函数与map方法

有一些函数的定义具有清晰简单的映射关系,可以使用匿名函数的方法简洁地表示。代码如下:

i_function= lambda y:2**y
print("i_function(5)=",i_function(5))
# i_function(5)= 32
multi_fuction =lambda x,y:x**y
print("multi_fuction(5,6)=",multi_fuction(5,6))
# multi_fuction(5,6)= 15625

Python 中提供了 map 函数来完成列表推导式的匿名函数映射,它返回的是一个 map 对象,需要通过 list 转为列表,代码如下:

# 单个输入值
print(list(map(lambda z:z**4,range(1,6,2))))
# [1, 81, 625]

#多个输入值的函数映射,可以通过追加迭代对象实现
print(list(map(lambda g,h:str(g)+'*'+h,range(1,6),list('qwert'))))
# ['1*q', '2*w', '3*e', '4*r', '5*t']

1.3 zip对象与enumerate方法

zip函数能够把多个可迭代对象打包成一个元组构成的可迭代对象,它返回了一个 zip 对象,通过 tuple, list 可以得到相应的打包结果。

list1,list2,list3=list('654'),list('cba'),list('321')
print(list(zip(list1,list2,list3)))
# [('6', 'c', '3'), ('5', 'b', '2'), ('4', 'a', '1')]
print(tuple(zip(list1,list2,list3)))
# (('6', 'c', '3'), ('5', 'b', '2'), ('4', 'a', '1'))
# 在循环迭代的时候使用zip 函数
for i,j,k in zip(list1,list2,list3):
    print("i=",i,"j=",j,"k=",k)
# i= 6 j= c k= 3
# i= 5 j= b k= 2
# i= 4 j= a k= 1
# enumerate 是一种特殊的打包,它可以在迭代时绑定迭代元素的遍历序号
list4=list('world')
for index,value in enumerate(list4):
    print("index=",index,"value=",value)
# index= 0 value= w
# index= 1 value= o
# index= 2 value= r
# index= 3 value= l
# index= 4 value= d
#或者使用zip函数实现
for index,value in zip(range(len(list4)),list4):
    print("index=", index, "value=", value)
# index= 0 value= w
# index= 1 value= o
# index= 2 value= r
# index= 3 value= l
# index= 4 value= d
# 利用 zip 对象对两个列表建立字典映射
print(dict(zip(list1,list2)))
# '6': 'c', '5': 'b', '4': 'a'}

# Python 提供了 * 操作符和 zip 联合使用来进行解压操作
zipped = list(zip(list1,list2,list3,list4[:3]))
print("zipped=",zipped)
# zipped= [('6', 'c', '3', 'w'), ('5', 'b', '2', 'o'), ('4', 'a', '1', 'r')]
print(list(zip(*zipped)))
# [('6', '5', '4'), ('c', 'b', 'a'), ('3', '2', '1'), ('w', 'o', 'r')]

二、Numpy基础

2.1 使用numpy构造数组

numpy构造数组常见的方法是使用array函数构造

import  numpy as np
print("数组=",np.array([i for i in range(1,15,3)]))
#数组= [ 1  4  7 10 13]
# 等差数列(linspace和arange)
print("等差数列=",np.linspace(1,10,20))# # 起始、终止(包含)、样本个数
# 等差数列= [ 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.        ]
print("数列=",np.arange(10,30,2))
# 数列= [10 12 14 16 18 20 22 24 26 28]
# 特殊矩阵
print("零矩阵=",np.zeros((3,4)))#零矩阵
# 零矩阵= [[0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]]
print("单位矩阵=",np.eye(4)) #单位矩阵
# 单位矩阵= [[1. 0. 0. 0.]
#  [0. 1. 0. 0.]
#  [0. 0. 1. 0.]
#  [0. 0. 0. 1.]]
print("偏移主对角线1个单位的伪单位矩阵=",np.eye(4,k=1))#偏移主对角线1个单位的伪单位矩阵
# 偏移主对角线1个单位的伪单位矩阵= [[0. 1. 0. 0.]
#  [0. 0. 1. 0.]
#  [0. 0. 0. 1.]
#  [0. 0. 0. 0.]]
print("矩阵=",np.full((3,2),1214))
# 矩阵= [[1214 1214]
#  [1214 1214]
#  [1214 1214]]

print("矩阵=",np.full((3,4),[1,2,1,4]))
# 矩阵= [[1 2 1 4]
#  [1 2 1 4]
#  [1 2 1 4]]

print("随机矩阵=",np.random.rand(4,4))
# 随机矩阵= [[0.03085034 0.7878708  0.39943908 0.61970093]
#  [0.28603138 0.92718978 0.42037367 0.59112997]
#  [0.56091549 0.90144402 0.67675756 0.14047721]
#  [0.60607429 0.85724591 0.19962022 0.59205343]]

2.2 numpy 数组的变形和合并

1、矩阵的转置

print("矩阵转置=",np.zeros((2,4)).T)
# 矩阵转置= [[0. 0.]
#  [0. 0.]
#  [0. 0.]
#  [0. 0.]]

2、矩阵合并(r_,c_)
相对于二维数组,r_表示上下合并,c_表示左右合并。

print("上下合并=",np.r_[np.zeros((3,4)),np.zeros((3,4))])
# 上下合并= [[0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]]
print("左右合并=",np.c_[np.zeros((3,4)),np.zeros((3,4))])
# 左右合并= [[0. 0. 0. 0. 0. 0. 0. 0.]
#  [0. 0. 0. 0. 0. 0. 0. 0.]
#  [0. 0. 0. 0. 0. 0. 0. 0.]]

3、维度变换(reshape)
reshape 可以将原数组按照新的维度重新排列,有两种使用模式,分别为 C 模式和 F 模式,分别以逐行和逐列的顺序进行填充读取。

print("上下合并=",np.r_[np.zeros((3,4)),np.zeros((3,4))])
# 上下合并= [[0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]]
print("左右合并=",np.c_[np.zeros((3,4)),np.zeros((3,4))])
# 左右合并= [[0. 0. 0. 0. 0. 0. 0. 0.]
#  [0. 0. 0. 0. 0. 0. 0. 0.]
#  [0. 0. 0. 0. 0. 0. 0. 0.]]

target=np.arange(1,11).reshape(2,5)
print("target=",target)
# target= [[ 1  2  3  4  5]
#  [ 6  7  8  9 10]]
print("target=",target.reshape((5,2),order='C')) #  # 行读取和填充
# target= [[ 1  2]
#  [ 3  4]
#  [ 5  6]
#  [ 7  8]
#  [ 9 10]]
print("target=",target.reshape((5,2),order='F')) #  列读取和填充
# target= [[ 1  8]
#  [ 6  4]
#  [ 2  9]
#  [ 7  5]
#  [ 3 10]]
# 由于被调用数组的大小是确定的, reshape 允许有一个维度存在空缺,此时只需填充-1即可
print("target=",target.reshape((5,-1)))
#  target= [[ 1  2]
#  [ 3  4]
#  [ 5  6]
#  [ 7  8]
#  [ 9 10]]

print("数组=",np.ones((5,1)).reshape(-1))# 将 n*1 大小的数组转为1维数组
# 数组= [1. 1. 1. 1. 1.]

2.3 numpy数组的切片与索引

numpy数组的切片模式支持使用 slice 类型的 start🔚step 切片,或者直接传入列表指定某个维度的索引进行切片。

target1=np.arange(2,17).reshape(3,5)
print("target1=",target1)
# target1= [[ 2  3  4  5  6]
#  [ 7  8  9 10 11]
#  [12 13 14 15 16]]
print(target1[:-1,[0,3]])
# [[ 2  5]
#  [ 7 10]]

还可以利用 np.ix_ 在对应的维度上使用布尔索引,但是不能使用 slice 切片。

print(target1[np.ix_([True,False,True],[False,True,True])])
# [[ 3  4]
#  [13 14]]
print(target1[np.ix_([1,3],[True,False,True])])
# [[ 3  4]
#  [13 14]]

2.4 numpy 常用函数

1、where
where是一种条件函数,可以指定满足条件与不满足条件位置对应的填充值。

x=np.array([-2,-1,0,1,2])
print(np.where(x>0,x,3))# 对应位置为True时填充a对应元素,否则填充3
# [3 3 3 1 2]

2、nonzero,argmax,argmin
nonzero,argmax,argmin函数返回的都是索引, nonzero 返回非零数的索引, argmax, argmin 分别返回最大和最小数的索引。

y=np.array([-6,-3,0,2,0,9,1])
print(np.nonzero(y))# 返回非零数的索引
# (array([0, 1, 3, 5, 6], dtype=int64),)
print(np.argmax(y))# 返回最大数的索引
# 5
print(np.argmin(y)) # 返回最小数的索引
# 0

3、any,all

any 指当序列至少 存在一个 True 或非零元素时返回 True ,否则返回 False all 指当序列元素 全为 True
或非零元素时返回 True ,否则返回 False

print(y.any())# 当序列至少 存在一个 True 或非零元素时返回 True ,否则返回 False
#True
print(y.all())# 当序列元素 全为 True 或非零元素时返回 True ,否则返回 False
#False

4、cumprod,cumsum,diff

cumprod, cumsum 分别表示累乘和累加函数,返回同长度的数组, diff
表示和前一个元素做差,由于第一个元素为缺失值,因此在默认参数情况下,返回长度是原数组减1

print(y.cumprod())# 累乘函数,返回同长度的数组
# [-6 18  0  0  0  0  0]
print(y.cumsum()) # 累加函数,返回同长度的数组
# [-6 -9 -9 -7 -7  2  3]
print(np.diff(y)) # 和前一个元素做差,由于第一个元素为缺失值,因此在默认参数情况下,返回长度是原数组减1
# [ 3  3  2 -2  9 -8]

5、numpy常用统计函数
常用的统计函数包括 max, min, mean, median, std, var, sum, quantile ,其中分位数计算是全局方法,因此不能通过 array.quantile 的方法调用。

target2=np.arange(12,27).reshape(3,5)
print(target2.max())# 最大值
# 26
print(target2.min())# 最小值
#12
print(target2.mean())#平均值
#19.0
print(np.median(target2))#中位数
#19.0
print(target2.std()) #标准差
#4.320493798938574
print(target2.var())#
#18.666666666666668
print(target2.sum()) #累加
#285
print(np.quantile(target2,0.5)) #分位数
#19.0
#需要注意含有缺失值的数组,它们返回的结果也是缺失值,如果需要略过缺失值,必须使用 nan* 类型的函数
target3=np.array([14,15,np.nan])
print("target3=",target3)# target3= [14. 15. nan]
print(target3.max()) #nan
print(np.nanmax(target3))# 15.0
print(np.quantile(target3,0.5)) # nan

2.5 向量与矩阵的计算

1、向量内积: dot

a ∗ b = ∑ i = 0 a i b i a*b=\sum_{i=0}^{}a_ib_i ab=i=0aibi

k=np.arange(12,17).reshape(1,5)
l=np.arange(12,17).reshape(5,1)
print("向量内积=",k.dot(l))
# 向量内积= [[990]]

2、向量范数和矩阵范数: np.linalg.norm
在矩阵范数的计算中,最重要的是 ord 参数,可选值如下:

ordnorm for matricesnorm for vectors
NoneFrobenius norm2-norm
‘fro’Frobenius norm-
‘nuc’nuclear norm-
infmax(sum(abs(x), axis=1))max(abs(x))
-infmax(sum(abs(x), axis=1))max(abs(x))
0-sum(x != 0)
1max(sum(abs(x), axis=0))as below
-1max(sum(abs(x), axis=0))as below
22-norm (largest sing. value)as below
-2smallest singular valueas below
other-sum(abs(x)ord)(1./ord)
参数说明计算方法
默认二范数: ℓ 2 \ell_2 2 x 1 2 + x 2 2 + . . . + x n 2 \sqrt{x^2_1+x^2_2+...+x^2_n} x12+x22+...+xn2
ord=2二范数: ℓ 2 \ell_2 2 x 1 2 + x 2 2 + . . . + x n 2 \sqrt{x^2_1+x^2_2+...+x^2_n} x12+x22+...+xn2
ord=1一范数: ℓ 1 \ell_1 1 ∣ x 1 ∣ + ∣ x 2 ∣ + . . . + ∣ x n ∣ \vert{x_1}\vert+\vert{x_2}\vert+...+\vert{x_n}\vert x1+x2+...+xn
ord=np.inf无穷范数: ℓ 2 \ell_2 2 m a x ( ∣ x i ∣ ) max(\vert{x_i}\vert) max(xi)

矩阵的范数:
1)ord=1:表示列和的最大值;ord=2:|λE-ATA|=0,求特征值,然后求最大特征值得算术平方根(matlab在线版,计算ans=ATA,[x,y]=eig(ans),sqrt(y),x是特征向量,y是特征值); ord=∞:表示行和的最大值; ord=None:默认情况下,是求整体的矩阵元素平方和,再开根号。(没仔细看,以为默认情况下就是矩阵的二范数,修正一下,默认情况下是求整个矩阵元素平方和再开根号)
2)axis:处理类型
axis=1表示按行向量处理,求多个行向量的范数
axis=0表示按列向量处理,求多个列向量的范数
axis=None表示矩阵范数。
3)keepding:是否保持矩阵的二维特性
True表示保持矩阵的二维特性,False相反

import numpy as np
x = np.array([
    [1, 2, 9],
    [3, 6, 7]])
print("默认参数(矩阵整体元素平方和开根号,不保留矩阵二维特性):",np.linalg.norm(x))
#默认参数(矩阵整体元素平方和开根号,不保留矩阵二维特性): 13.416407864998739
print("矩阵整体元素平方和开根号,保留矩阵二维特性:",np.linalg.norm(x,keepdims=True))
# 矩阵整体元素平方和开根号,保留矩阵二维特性: [[13.41640786]]
print("矩阵每个行向量求向量的2范数:",np.linalg.norm(x,axis=1,keepdims=True))
# 矩阵每个行向量求向量的2范数: [[9.2736185 ]
#  [9.69535971]]
print("矩阵每个列向量求向量的2范数:",np.linalg.norm(x,axis=0,keepdims=True))
# 矩阵每个列向量求向量的2范数: [[ 3.16227766  6.32455532 11.40175425]]
print("矩阵1范数:",np.linalg.norm(x,ord=1,keepdims=True))
# 矩阵1范数: [[16.]]
print("矩阵2范数:",np.linalg.norm(x,ord=2,keepdims=True))
# 矩阵2范数: [[12.96543469]]
print("矩阵∞范数:",np.linalg.norm(x,ord=np.inf,keepdims=True))
# 矩阵∞范数: [[16.]]
print("矩阵每个行向量求向量的1范数:",np.linalg.norm(x,ord=1,axis=1,keepdims=True))
# 矩阵每个行向量求向量的1范数: [[12.]
#  [16.]]

3、矩阵乘法(@)
[ A m ∗ p B p ∗ n ] = ∑ k = 1 p A i k B k j \left[{A}_m*_p{B}_p*_n\right]=\sum_{k=1}^p A_ikB_kj [AmpBpn]=k=1pAikBkj

k=np.arange(2,17).reshape(3,5)
l=np.arange(22,37).reshape(5,3)
print("矩阵乘法=",k@l)
# 矩阵乘法= [[ 590  610  630]
#  [1290 1335 1380]
#  [1990 2060 2130]]

三、编程实践

例1、利用列表推导式写矩阵乘法

# 利用列表推导式写矩阵乘法
Mat1=np.random.rand(3,4)
Mat2=np.random.rand(4,3)
res=[[sum([Mat1[i][k]*Mat2[k][j] for k in range(Mat1.shape[1])]) for j in range(Mat2.shape[1]) ] for i in range(Mat1.shape[0])]
print(res) # [[0.6094751440030487, 0.7794174334232945, 1.0235658354677835], [0.6026038797348408, 0.7960478062763812, 1.0565907210550096], [0.7642209907651294, 0.8786058750405498, 1.1479216227691413]]
print(((Mat1@Mat2 -res)<1e-15).all())# True

例2、卡方统计量

#卡方统计量
np.random.seed(0)
M=np.random.randint(30,40,(8,5))
N=M.sum(0)*M.sum(1).reshape(-1,1)/M.sum()
res=((M-N)**2/N).sum()
print("res=",res)
# res= 4.857870907431414

参考文献

https://datawhalechina.github.io/joyful-pandas/build/html/%E7%9B%AE%E5%BD%95/ch1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值