Python pandas(一)- 预备知识

一、Python 基础
1.1 列表推导式

列表推导式将多行for循环写在一行上,使程序看起来简洁,需注意:多层嵌套时,易读性差,需要注意嵌套的顺序,列表推导式内部也会有列表推导式,用 [] 区分

  1. [ ? for i in ?] 。其中,第一个 ? 为映射函数,其输入为后面 i 指代的内容,第二个 ? 表示迭代的对象。
[i ** 2 for i in range(5)]
# 输出: [0, 2, 4, 6, 8]
  1. 列表表达式多层嵌套
[m + '_' + n for m in ['a', 'b'] for n in ['c', 'd']]
# 输出:['a_c', 'a_d', 'b_c', 'b_d']

其中,第一个第一个 for 为外层循环,第二个为内层循环。
对应练习题:练习题1

1.2 条件赋值语句
  1. 形式为:value = a if condition else b
value = 'cat' if 2>1 else 'dog'
value
# 输出:'cat'

value = 'cat' if 2<1 else 'dog'
value
# 输出:'dog'
  1. 条件赋值与for循环
    练习1:列表中最大值为5,将大于5的数值改写为5
L1 = [1, 2, 3, 4, 5, 6, 7]
res1 = [i if i <= 5 else 5 for i in L1]
res1
# 输出:[1, 2, 3, 4, 5, 5, 5]

练习2:去除列表中的大于5的元素及重复元素

# (1) 用 “条件赋值语句”
L2 = [1, 7, 4, 3, 5, 6, 7, 1, 3]
L2 = sorted(list(set(L2)), reverse=False)
res2 = [i  if i <=5 else 6 for i in L2]
try:
    res2 = res2[0: res2.index(6)]
except:
    res2 = res2
res2
# 输出:[1, 3, 4, 5]
# (2) 基于numpy
import numpy as np
L3 = [1, 7, 4, 3, 5, 6, 7, 1, 3]
L3 = np.array(L3)
res3 = list(set(L3[L3 <= 5]))
res3
# 输出:[1, 3, 4, 5]
1.3 匿名函数与map方法

当函数的定义具有明显的映射关系的时候,用匿名函数 lambda 可以简洁表示:

list(map(lambda x: 2*x, range(5)))
# 输出:[0, 2, 4, 6, 8]

注意:map对象需要通过list转为列表

1.4 zip 对象和enumerate
  1. 在 Python 3.x 中为了减少内存,zip() 返回的是一个迭代器,通过 tuple, list 可以得到相应的打包结果:
L1, L2, L3 = list('abc'), list('def'), list('hij')
list(zip(L1, L2, L3))
# 输出:[('a', 'd', 'h'), ('b', 'e', 'i'), ('c', 'f', 'j')]
dict(zip(L1, L2))
# 输出字典映射:{'a': 'd', 'b': 'e', 'c': 'f'}
  1. 在 for 循环中,如果想要同时遍历多个 list,可用 zip 函数进行迭代打包:
list1 = list('123')
list2 = list('abc')
for i, j in zip(list1, list2):
    print(i, j)
# 输出: 1 a
#       2 b
#       3 c
  1. zip() 函数解压
L1, L2, L3 = list('abc'), list('def'), list('hij')
zipped = list(zip(L1, L2, L3))
zipped
# 输出:[('a', 'd', 'h'), ('b', 'e', 'i'), ('c', 'f', 'j')]

# 解压
list(zip(*zipped))
# 输出:[('a', 'b', 'c'), ('d', 'e', 'f'), ('h', 'i', 'j')]
  1. enumerate方法
    既要遍历索引又要遍历元素是采用 enumerate 方法。
L = ['It', 'is', 'a', 'dog', '!']
for index, value in enumerate(L):
     print(index, value)
# 输出: 0 It
#       1 is
#       2 a
#       3 dog
#       4 !
二、Numpy 基础
2.1 np数组的生成方式
  1. 生成随机数据
import numpy as np
L1 = np.linspace(1,5,11)       # 起始、终止(包含)、样本个数
L2 = np.arange(1,7,2)          # 起始、终止(不包含)、步长
L3 = np.zeros((2,3))           # 2 * 3 维度的0矩阵,输入的是元组(2,3)
L4 = np.zeros(3)
L5 = np.eye(3)                 # 3 * 3 的单位矩阵,主对角线上的值为1
L6 = np.eye(3, k=1)            # 偏移主对角线1个单位的伪单位矩阵
L7 = np.full((2,3), 10)        # 大小为2 * 3,值为10的矩阵
L8 = np.full((2,3), [1,2,3])   # 大小为2 * 3,每一行的取值为[1,2,3]
# 均匀分布
L_1 = np.random.rand(3)         # 生成服从0-1 均匀分布 的3个随机数
L_2 = np.random.rand(3, 3)      # 生成服从0-1均匀分布,大小为3 * 3的随机矩阵

a, b = 5, 15
L_3 = (b - a) * np.random.rand(3) + a  # 服从区间 a 到 b 上的均匀分布的3个随机数
# 正太分布
L_4 = np.random.randn(3)       # 生成服从 0-1 正态分布 的3个随机数
L_5 = np.random.randn(2, 3)

sigma, mu = 2.5, 3
L_6 = mu + np.random.randn(3) * sigma   # 标准差为sigma,均值为mu的正态分布
# 随机整数
low, high, size = 5, 10, (2,3)
L9 = np.random.randint(low, high, size)
  1. 随机选择数据 choice
    choice 可以从给定的列表中,以一定概率和方式抽取结果,当不指定概率时为均匀采样,默认抽取方式为有放回抽样;
    应用:ML中划分 train set、valid set、test set 时,可用随机抽取样本的方式,python实现上用 np.choice
my_list = ['a', 'b', 'c', 'd']
# 从my_list中,以概率p抽取2个数据
np.random.choice(my_list, 2, replace=False, p=[0.1, 0.7, 0.1 ,0.1])
# 输出:array(['b', 'c'], dtype='<U1')

np.random.choice(my_list, (3,3))
  1. 随机种子 - 使结果可复现
np.random.seed(0)
np.random.rand()
# 输出:0.5488135039273248
np.random.seed(0)
np.random.rand()
# 输出:0.5488135039273248

同时设置随机种子为0,生成的随机数的结果相同

2.2 变形与合并
  1. 变形
# 转置 .T
np.zeros((2,3)).T
# reshape, 把原数组按照新的维度重新排列
target = np.arange(8).reshape(2,4)
target
# 输出:array([[0, 1, 2, 3],
#              [4, 5, 6, 7]])

.reshape 在使用时有两种模式,分别为C模式F模式,分别以逐行逐列的顺序进行填充读取。

target.reshape((4,2), order='C') # 按照行读取和填充,0 1 2 3 4 5 6 7 8 9 
# 输出:array([[0, 1],
#              [2, 3],
#              [4, 5],
#              [6, 7]])

target.reshape((4,2), order='F') # 按照列读取和填充,0 2 4 6 1 3 5 7
# 输出:array([[0, 2],
#              [4, 6],
#              [1, 3],
#              [5, 7]])
  1. 合并
    学习资料中给出的是 **r_ ** 和 **c_ ** 进行数组的合并:
# 对于二维数组,r_和c_分别表示上下合并和左右合并
np.r_[np.zeros((2,3)),np.zeros((2,3))]
# 输出:array([[0., 0., 0.],
#             [0., 0., 0.],
#             [0., 0., 0.],
#             [0., 0., 0.]])

np.c_[np.zeros((2,3)),np.zeros((2,3))]
# 输出:array([[0., 0., 0., 0., 0., 0.],
#              [0., 0., 0., 0., 0., 0.]])
# 对于一维数组,r_和c_
np.r_[np.zeros(3),np.zeros(3)]
# 输出:array([0., 0., 0., 0., 0., 0.])

np.c_[np.zeros(3),np.zeros(3)]
# array([[0., 0.],
#        [0., 0.],
#        [0., 0.]])

除此之外,np.vstack()np.hstack() 也用于数组的合并

np.vstack((np.zeros((2,3)),np.zeros((2,3))))
# 输出:array([[0., 0., 0.],
#              [0., 0., 0.],
#              [0., 0., 0.],
#              [0., 0., 0.]])

np.hstack((np.zeros((2,3)),np.zeros((2,3))))
# 输出:array([[0., 0., 0., 0., 0., 0.],
#              [0., 0., 0., 0., 0., 0.]])
2.3 数组的切片与索引

list[start : end : step] 切片,还可以直接传入列表指定某个维度的索引进行切片;
利用 np.ix_ 在对应的维度上使用布尔索引,但此时不能使用slice切片:

target = np.arange(9).reshape(3,3)
target
# 输出:array([[0, 1, 2],
#              [3, 4, 5],
#              [6, 7, 8]])
target[np.ix_([True, False, True])]  # 输出target的前两行
# 输出:array([[0, 1, 2],
#              [6, 7, 8]])

target[np.ix_([True, False, True], [True, False, True])]  # 第一个布尔为行索引,第二个布尔为列索引
# 等价于 target[np.ix_([0,2], [True, False, True])]   这里的[0,2]不能是切片,只能单独索引某一个维度
# 输出:array([[0, 2],
#              [6, 8]])
2.4 一些常用函数
# (1)np.where 条件函数查找,有点类似于条件赋值语句
a = np.array([3,1,-1,0])
np.where(a>0, a, 5)     # 满足a>0则对应位置填充a对应的元素,否则填充5
# 输出:array([3, 1, 5, 5])
# (2)np.nonzero() 返回非零数字的索引
a = np.array([-2,-5,0,1,3,-1])
np.nonzero(a)   # 索引为2的地方为0
# 输出:(array([0, 1, 3, 4, 5], dtype=int64),)

# (3)np.argmax(), np.argmin() 返回最大和最小数的索引
a.argmax()  # 4
a.argmin()  # 1
# (4) np.any(), np.all()
a = np.array([0,1])
a.any()  # any 指当序列至少 存在一个 True 或非零元素时返回 True,否则返回 False
# 输出:True 

a.all()  # all 指当序列元素全为 True 或非零元素时返回 True,否则返回 False
# 输出:False
# (5) np.cumprod() 累乘; np.cumsum() 累加
a = np.array([1,3,3,4])
a.cumprod()    
# 输出:array([ 1,  3,  9, 36], dtype=int32)

a.cumsum()
# 输出:array([ 1,  3,  6, 10], dtype=int32)
# (6) np.diff() 和前一个元素做差,由于第一个元素为缺失值,因此在默认情况下,返回长度是原数组减1
np.diff(a)
# 输出:array([2, 0, 1])

np.diff() 的可能应用场景:时间序列预测 or 分类问题中构造特征;例如,基于银行存款数据预测某人是否存在贷款违约风险,可用当月存款 - 上月存款,构造新的特征。

# (7) 相关系数,协方差
target1 = np.array([1,3,5,9])
target2 = np.array([1,5,3,-9])
np.cov(target1, target2)       # 协方差
np.corrcoef(target1, target2)  # 相关系数
2.5 广播机制

广播机制用于处理两个不同维度数组之间的操作;

  1. 标量和数组
# 一个标量和数组进行运算时,标量会自动把大小扩充为数组大小,之后进行逐元素操作:
res = 3 * np.ones((2,2)) + 1
res
# 输出:array([[4., 4.],
#              [4., 4.]])
  1. 二维数组和二维数组
    当两个数组维度完全一致时,使用对应元素的操作,否则会报错;
    除非其中的某个数组的维度是 𝑚×1 或者 1×𝑛 ,那么会扩充其具有 1 的维度为另一个数组对应维度的大小。例如, 1×2 数组和 3×2 数组做逐元素运算时会把第一个数组扩充为 3×2 ,扩充时的对应数值进行赋值。但是,需要注意的是,如果第一个数组的维度是 1×3 ,那么由于在第二维上的大小不匹配且不为 1 ,此时报错。
2.6 矩阵相乘
  1. 向量内积
a = np.array([1,2,3])
b = np.array([1,3,5])
a.dot(b) # 22
  1. 矩阵范数
    函数参数如下:矩阵范数
x_norm=np.linalg.norm(x, ord=None, axis=None, keepdims=False)
  1. 矩阵乘法
a = np.arange(4).reshape(-1,2)
b = np.arange(-4,0).reshape(-1,2)
a@b   # @ 符号在python中的计算方式和线性代数中的矩阵相乘相同
a*b   # 矩阵对应元素相乘
三、练习题
  1. 利用列表推导式写矩阵乘法
    一般的矩阵乘法根据公式,可以由三重循环写出,请将其改写为列表推导式的形式。
# 错误版本1:列表推导式的嵌套顺序错,无法运行输出结果
M1 = np.random.rand(2,3)
M2 = np.random.rand(3,4)
res = [sum(M1[i,k] * M2[k,j]) for i in range(M1.shape[0]) for j in range(M2.shape[1]) for k in range(M1.shape[1])]
res

# 错误版本2 列表推导式的嵌套顺序错,运行出错误的结果
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])]
res = np.array(res).reshape(M1.shape[0], M2.shape[1])
((M1@M2 - res) < 1e-15).all() # 排除数值误差

# 正确答案
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])]
((M1@M2 - res) < 1e-15).all() # 排除数值误差
  1. 更新矩阵
    在这里插入图片描述
    分析:利用 numpy 的广播机制实现,矩阵A利用np.arange()生成;(1/A).sum(1)之后要利用reshape改变形状,否则广播错误!
A = np.arange(1,10).reshape(3, -1)
A_ = (1/A).sum(1).reshape(-1,1) 
B = A * A_
B
  1. 卡方统计量
    在这里插入图片描述
    分析:B的分母是矩阵A中元素的和,分子是A的第 j 列和A的第 i 行的乘机(广播)!
np.random.seed(0)
A = np.random.randint(10, 20, (8, 5))
B = A.sum(0)*A.sum(1).reshape(-1, 1)/A.sum()
ka = ((A-B)**2/B).sum()
ka   # 11.842696601945802

Pandas 学习,Day1,打卡~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值