task1 pandas基础

一、作业

  1. 利用列表推导式写矩阵乘法。一般的矩阵乘法根据公式,可以由三重循环写出。请将其改写为列表推导式的形式。
#作业
M1 = np.random.rand(2,3)
M2 = np.random.rand(3,4)
res = np.empty((M1.shape[0],M2.shape[1]))
for i in range(M1.shape[0]):
     for j in range(M2.shape[1]):
        item = 0
        for k in range(M1.shape[1]):
             item += M1[i][k] * M2[k][j]
        res[i][j] = item
(abs(M1@M2 - res) < 1e-15).all() # 排除数值误差
print(res)
#没有想好sum应该怎么放,所以就在后面手动加sum的初级答案
res1 = np.array([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])]).reshape(M1.shape[0],M2.shape[1],-1).sum(axis=2)
res1
#答案
res2 = [[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])]
(abs(M1@M2 - res2) < 1e-15).all() # 排除数值误差
#后面又想直接两层
result = np.array([[np.sum(row*col) for col in Mat2.T ] for row in Mat1  ])
  1. 作业2设矩阵 Am×n ,现在对 A 中的每一个元素进行更新生成矩阵 B ,更新方法是 Bij=Aij∑k=1n1Aik ,
A= np.arange(1,10).reshape(3,3)
#法一,受第一题,就想用列表推导式做一下
B = [ [A[r][c] * np.sum(1/A[r,:]) for c in range(A.shape[1])] for r in range(A.shape[0])  ]
#法二
B = A*(1/A).sum(1).reshape(-1,1)
B
#A*(1/A).sum(1).reshape(-1,1)
  1. 计算卡方统计量
np.random.seed(0)
A = np.random.randint(10, 20, (8, 5))
A
B = (A.sum(axis=0)*A.sum(axis=1).reshape(-1,1))/A.sum()
B
((A-B)**2/B).sum()
  1. 改进矩阵计算的性能
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))
##竟然是先化简公式。。。大意了
(((B**2).sum(1).reshape(-1,1)+(U**2).sum(0)-2*B@U)*Z).sum()
  1. 连续整数的最大长度
    开始的思路是首先错位相减,然后想办法寻找有几个连续的1,这个想的是用if else把非1的替换成0,再nonzeros索引,结果后面还是回到了怎么找几个连续的1。想法错误,看了下,反而是找有几个连续的0,这样通过相减,可以直接得到个数。
def int_Numpy(int_arr):
    int_arr_1 = np.diff(x)!=1
    int_arr_2 = np.r_[1,int_arr_1,1]
    int_arr_3 = np.nonzero(int_arr_2)
    int_arr_4 = np.diff(int_arr_3).max()
    return int_arr_4
int_Numpy(np.array([3,2,2,3,4,6]))

二、

2.1 列表推导式

等价于* for i in * (第一个指的是映射函数,输入的是i指代的内容,第二个指遍历的范围)

L= []
def my_func(c):
    return 2*c
for i in range(5):
    L.append(my_func(i))
L


[my_func(i) for i in range(5)]#不加[]是错的,无具体形式
# 多层嵌套
print(i)#4 
x = [i for row in range(3) for cul in range(4)]
print(x) #[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],注意,这里的i由于之前已赋值为4,因此总是为4,

x = [j for j in range(3) for j in range(4)]#顺序为j=0,再重新遍历赋值为0-3;而后j=1...
print(x) #[0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3],等价于
M = []
for j in range(3):
    for j in range(4):
        M.append(j)

#构造一个3*4的矩阵
y = [[i for i in range(3)] for i in range(4)]
y#[[4, 4, 4], [4, 4, 4], [4, 4, 4], [4i, 4, 4]]
#等价于
M = []
N = []
for i in range(3):
    M.append(i)
for j in range(4):
        N.append(M)
N #[[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]]


m = [[i for i in range(3)] for j in range(4)]
m#[[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]]
#等价于
N = []
for i in range(3):
    M = []
    for j in range(4):
        M.append(j)
    N.append(M)
N

[m+n for m in ['a','b'] for n in ['c','d']]


x = [j for j in range(3) for j in range(4)]
print(x)
#[0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
M = []
N = []
for i in range(3):
    M.append(i)
for j in range(4):
        N.append(M)
N 
y = [[i for i in range(3)] for i in range(4)]
y


N = []
for i in range(3):
    M = []
    for j in range(4):
        M.append(j)
    N.append(M)
N

2.2 匿名函数与map方法

lambda函数:也叫匿名函数,具体形式为:lambda 函数变量:函数表达式

lambda x: 2*x**2 - 6*x + 9
(lambda x: 2*x**2 - 6*x + 9)(2)#5
L = [(lambda x: 2*x**2 - 6*x + 9)(i) for i in range(3)]#经常用于列表推导式
L #[9, 5, 5]

map函数:map(func,seq)就是将函数作用在序列的每个元素上,然后创建由函数返回值组成的列表。
#注意,map不改变原list,而是返回一个新list。python3返回迭代器,python2返回值。

L1 = list(range(3))
map(lambda x: 2*x**2 - 6*x + 9,L1)#python3返回迭代器,python2返回值
#<map at 0x2b04168a5e0>
List = [i for i in map(lambda x,y: x+y,[1,3,5,7,9],[2,4,6,8,10])]#多个输入值的函数映射,可以追加迭代对象实现:
List#[3, 7, 11, 15, 19]
#但是可以用list转换为列表
list(map(lambda x: 2*x**2 - 6*x + 9,range(3)))
#[9, 5, 5]

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

L1,L2,L3 = list('abc'),list('def'),list('ghi')
list(zip(L1,L2,L3))#[('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i')]
tuple(zip(L1,L2,L3))#(('a', 'd', 'g'), ('b', 'e', 'h'), ('c', 'f', 'i'))
#往往会在循环迭代的时候使用到 zip 函数:每组第一个构成第一组迭代对象,每组第二个构成第二组迭代对象...
for i,j,k in zip(L1,L2,L3):
    print(i,j,k)
#a d g
#b e h
#c f i
#enumerate 是一种特殊的打包,它可以在迭代时绑定迭代元素的遍历序号,先是序号,后是值
L = list('abcd')
for index,value in enumerate(L):
    print(index,value)
#0 a
#1 b
#2 c
#3 d
#也可用zip
for index,value in zip(range(len(L)),L):
    print(index,value)
#
dict(zip(L1,L2))#{'a': 'd', 'b': 'e', 'c': 'f'}

2.3 numpy基础

numpy库对应数值计算,大部分运算与matlab相似。

import numpy as np#numpy库对应数值计算,大部分运算与matlab相似
# 1构造数组
np.array(range(5))#array([0, 1, 2, 3, 4])

2 特殊矩阵的构造方式

# 2.1等差序列函数为np.linspace,np.arange
np.linspace(1,5,9)#array([1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ])
#np.linspace第一个数为起始值,第二个数为末尾值(包含值),第三个为个数
np.linspace(1,2)#默认个数为50?
np.arange(1,5,0.5)#array([1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
#np.arange第一个数为起始值,第二个数为末尾值(不包含值),第三个为步长
np.arange(10)#array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),默认从0开始,步长为1
#2.2 特殊矩阵构造,zeros,eye,full,zeros与eye的用法类似matlab。
np.zeros((2,3))##当生成多维的话,函数括号里面一定要是元组类型的一组数组,不然就只能是一维
np.zeros((2,3,2))#从最外层往里看,有多少个就是左边第一个维度,以此类推
#array([[[0., 0.],
#        [0., 0.],
#        [0., 0.]],

#       [[0., 0.],
#        [0., 0.],
#        [0., 0.]]])
np.eye(3)#3*3的单位矩阵
np.eye(5)#生成单位矩阵,但是输入只有一个,所以只能生成矩阵而不能是张量
np.eye(3,k=1)#array([[0., 1., 0.],# 偏移主对角线1个单位的伪单位矩阵
#       [0., 0., 1.],
#       [0., 0., 0.]])
#k取值为正时,往右上角移,为负为往左下角移
np.full((2,3),10)
np.full((2,3),[1,2,3])
#np.full((2,3),[1,2])#报错,因为1*2的矩阵不能传播给2*3大小的。
## 2.3随机矩阵rondom
#最常用的随机生成函数为 rand, randn, randint, choice ,
#它们分别表示0-1均匀分布的随机数组、标准正态的随机数组、随机整数组和随机列表抽样
np.random.rand(3,3)#注意括号内不是元组的形式
a,b=2,10#生成a.b之间的随机数组
(b-a)*np.random.rand(2,3)+a
np.random.randn(3,2)
#生成均值为a,标准差为b*I的正太分布数组
np.random.randn(3,2)*(b**2)+a
#randint 可以指定生成随机整数的最小值最大值(不包含)和维度大小
low,high,size = 2,11,(2,3)
np.random.randint(low,high,size)#不加size就是一个数
#choice 可以从给定的列表中,以一定概率和方式抽取结果,当不指定概率时为均匀采样,默认抽取方式为有放回抽样:
List = np.array(range(5))
np.random.choice(List,2,replace=False,p=[0.1, 0.6, 0.1 ,0.1,0.1])#False表示不放回抽回,True为有放回
np.random.choice(List,(3,2))
#使用 permutation 函数打散原列表
List1 = ['a','b','c','d']
np.random.choice(List1,len(List1),replace=False)# 也可打散原列表
np.random.permutation(List1)
## 2.4 随机种子能够固定随机数的输出结果:
#使下一次生成的随机数为由种子数决定的“特定”的随机数,如果seed中参数为空,则生成的随机数“完全”随机,seed中没有特定含义
np.random.seed(1)
a = np.random.random(1)
a#array([0.417022])
a
np.random.seed(1)
np.random.random(1)#array([0.417022])
np.random.random(1)#array([0.72032449])

3 np数组的变形与合并

##3.1np数组的变形与合并
#转置,T方法或者transpose函数
np.zeros((2,3)).T#等价于
np.transpose(np.zeros((2,3)))
#合并操作: r_, c_,对于二维数组而言,r_ 和 c_ 分别表示上下合并和左右合并:
np.r_[np.zeros((2,3)),np.zeros((2,3))]### 注意是用[]括起来
np.c_[np.zeros((2,3)),np.zeros((2,3))]
#一维数组和二维数组进行合并时,应当把其视作列向量,在长度匹配的情况下只能够使用左右合并的c_ 操作:
np.c_[np.array([4,8]),np.zeros((2,3))]
#array([[4., 0., 0., 0.],
#       [8., 0., 0., 0.]])
## 纬度变换,reshape是np库的一种方法,指轴对换
#可以是np中的对象.reshape,也可以是函数np.reshape(),函数里面有三个参数,
#np.reshape(np.arange(12),(4,3),order='C'),第一个是变换的数组,第二个是变换后的大小,第三个指的是按行还是列变换
#C-逐行,F-逐列的顺序进行填充读取。按行读取的意思是,每行为一个单元,从左至右读的顺序为原来数组按行的顺序,而后下一行,
#按列读取的意思是,每列为一个单元,从上至下读的顺序为原来数组按列的顺序,而后下一列
arr5 = np.reshape(np.arange(12),(4,3),order='C')
#array([[ 0,  1,  2],
#       [ 3,  4,  5],
 #      [ 6,  7,  8],
 #      [ 9, 10, 11]])
arr6 = np.reshape(np.arange(12),(3,4))
#array([[ 0,  1,  2,  3],
#       [ 4,  5,  6,  7],
#       [ 8,  9, 10, 11]])
arr6 = np.reshape(np.arange(12),(3,4),order='F')
arr6
#array([[ 0,  3,  6,  9],
#       [ 1,  4,  7, 10],
#       [ 2,  5,  8, 11]])
target = np.arange(8).reshape(2,4)
target
#array([[0, 1, 2, 3],
 #      [4, 5, 6, 7]])
target.reshape((4,2),order = 'C')
#array([[0, 1],
#       [2, 3],
#       [4, 5],
#       [6, 7]])
target.reshape((4,2),order = 'F')
#array([[0, 2],
#       [4, 6],
 #      [1, 3],
 #      [5, 7]])
## 特别地,由于被调用数组的大小是确定的, reshape允许有一个维度存在空缺,此时只需填充-1即可:
target.reshape((4,-1),order = 'F')#与上步数值一致
# 将n*1大小的数组转为1维数组
target1 = np.arange(6)
target1.reshape(-1)
target2 = np.ones((3,1))
target2
#array([[1.],
#       [1.],
#       [1.]])
target2.reshape(-1)
#array([1., 1., 1.])

arr1.transpose((1,0,2))#array([[[ 0,  1,  2,  3],
#        [ 8,  9, 10, 11]],

 #      [[ 4,  5,  6,  7],
 #       [12, 13, 14, 15]]])
#(1,0,2)的意思是第一个轴变成了第2个,第2个轴变成了第一个,第3个轴不变。
#[a11=[里面是4个数0123,不变],a12=[里面是4个数4567,不变]]这是原来相当于矩阵的第一行的内容
#[a21=[里面是4个数891011,不变],a22=[里面是4个数1213141516,不变]]这是原来第二行的内容
#由于转置,因此a12与a21的位置互换,因此变为
#.transpose能处理张量,指定的轴(维度)交换,.T只能是处理矩阵的


4 索引和切⽚,与matlabl类似,但是用中括号,而且从0开始,也是最后一个取不到。

#索引和切⽚,与matlabl类似,但是用中括号,而且从0开始,也是最后一个不到
arr1 = np.arange(10)
arr1[5]#5
arr1[5:8]#array([5, 6, 7])
#注意的是,数组的切片选取的是原来的视图??相当于把原来的地址取出来了,
#如果改变这个切片的值,相当于把这个地址指向改变了,因此原来的数组也会变
arr1[5:8] = 12
arr1 #array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])
#当你将⼀个标量值赋值给⼀个切⽚时(如
#arr[5:8]=12),该值会⾃动传播(也就说后⾯将会讲到的“⼴ 播”)到整个选区,广播一定要和索引搭配
#但是如果是下面这种,就是对这个变量直接赋值,而不是广播
arr1_slice = arr1[5:8] 
arr1_slice = 15
arr1_slice#15
arr1#array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])不改变值
arr1_slice2 = arr1[5:8] 
arr1_slice2[1] = 12345
arr1#array([    0,     1,     2,     3,     4,    12, 12345,    12,     8,
        #   9])改变原来的值
arr2 = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr2[2]#array([7, 8, 9])
arr2[2][2]#9
arr2[2,2]#9
arr3 = np.arange(12).reshape(2,2,3)
arr3
'''array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])'''
arr3[0]#array([[0, 1, 2],
      # [3, 4, 5]])
arr3[0,1]#array([3, 4, 5])
arr3[0]=44
arr3
'''
array([[[44, 44, 44],
        [44, 44, 44]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])
'''
#切片是沿着行来选取的
arr3[:2]#start:end[:step],要给定步长一定要两个冒号,:2表示选取前两行。只有一个说明是最外面的大层取前两行
arr3[:2][:1]#array([[[44, 44, 44],
        #[44, 44, 44]]])
arr3[:2,:1]#array([[[44, 44, 44]],

     #  [[ 6,  7,  8]]])
arr3[1:]#:1和1:的区别:
#将整数索引和切片混合可以得到低维度的数组
arr3[1,:1]#array([[6, 7, 8]])

  
#布尔值索引
names = np.array(['Bob','Joe','Will','Bob'])
data = np.random.randn(4,4)
names
print(data)#[[ 1.08979836 -1.72194748  0.80929756  1.37038419]
# [-0.41274112  0.90199302  0.58407842 -1.61763921]
# [-0.99331377  0.04137762 -0.69626801 -0.170982  ]
# [ 1.17256463  1.68120098 -0.5011575   1.29466767]]
names == 'Bob'
data[names == 'Bob']#同样的是把里面的一行的布尔值广播成4行的去取值
#array([[ 1.08979836, -1.72194748,  0.80929756,  1.37038419],
  #     [ 1.17256463,  1.68120098, -0.5011575 ,  1.29466767]])
#布尔型数组的⻓度必须跟被索引的轴⻓度⼀致。
data[names == 'Bob',2:]#取1、4行的后两列
#可以使⽤不等于符号(!=),也可以通过~对条件进⾏否定:
cond = names == 'Bob'
data[~cond] # [-0.41274112  0.90199302  0.58407842 -1.61763921]
# [-0.99331377  0.04137762 -0.69626801 -0.170982  ]
#选取这三个名字中的两个需要组合应⽤多个布尔条件,使⽤&(和)、|(或)之类的布尔算术运算符即可:
#注意布尔型不用and和or

##此外,还可以利用 np.ix_ 在对应的维度上使用布尔索引,但此时不能使用 slice 切片:
data[np.ix_([True,False,False,True])]#取1、4个第一维度的值
data[np.ix_([True,False,False,True],[True,False,False,True])]#1、1,1、4,4、1,4、4
#当数组维度为1维时,可以直接进行布尔索引,而无需 np.ix_ :
names[names == 'Bob']

#可以用整数数组来进行索引,也就是可以给一个数组来指定选取哪几行
#花式索引,花式索引跟切⽚不⼀样,它总是将数据复制到新数组中。也就是把值取出来放到一个新的数组。
#切片是针对地址内存储的东西,展示出来
arr4 = np.empty((8,4))
arr4=[i for i in range(4)]
arr4
arr4[[0,4,5],[0,1,3]] # array([0.,4.,5.])
arr4[[0,4,5],[0,1,3]] = 9
arr4#array([[9., 0., 0., 0.],
     #  [1., 1., 1., 1.],
 #      [2., 2., 2., 2.],
 #      [3., 3., 3., 3.],
 #      [4., 9., 4., 4.],
 #      [5., 5., 5., 9.],
  #     [6., 6., 6., 6.],
   #    [7., 7., 7., 7.]])

5常用函数

#常用函数
#1 where,#where的第一个参数是判定条件,第二个是True的代替值,第三个参数是False的代替值
arr2 = np.random.randn(4,4)
res2 = np.where(arr2>0,2,-2)#where的第一个参数是判定条件,第二个是True的代替值,第三个参数是False的代替值
res2#array([[-2,  2,  2, -2],
   #    [ 2, -2, -2, -2],
  #     [-2,  2,  2, -2],
   #    [-2,  2, -2,  2]])
res3 = np.where(arr2>0,2,arr2)
res3#array([[ 2.        , -1.62874159,  2.        , -0.43803403],
  #     [ 2.        ,  2.        ,  2.        ,  2.        ],
 #      [ 2.        , -0.74773813,  2.        ,  2.        ],
  #     [-0.4025746 ,  2.        , -0.55752542, -1.90434236]])
#传递给where的数组⼤⼩可以不相等,甚⾄可以是标量值。

# 2 nonzero, argmax, argmin
#这三个函数返回的都是索引, nonzero 返回非零数的索引, argmax, argmin 分别返回最大和最小数的索引:
a = np.array([-2,-5,0,1,3,-1])
np.nonzero(a)#(array([0, 1, 3, 4, 5], dtype=int64),)
a.argmax()
#4
a.argmin()
#1
#3 any, all,any 指当序列至少 存在一个 True 或非零元素时返回 True ,否则返回 False
#all 指当序列元素 全为 True 或非零元素时返回 True ,否则返回 False
a = np.array([0,1])
a.any()# True
a.all()#False
#4 cumprod, cumsum, diff. cumprod, cumsum 分别表示累乘和累加函数,返回同长度的数组
#diff 表示和前一个元素做差,由于第一个元素为缺失值,因此在默认参数情况下,返回长度是原数组减1
a = np.array([1,2,3])
a.cumprod()
#array([1, 2, 6], dtype=int32)
a.cumsum()
#array([1, 3, 6], dtype=int32)
np.diff(a)
#array([1, 1])
# 5统计函数
#常用的统计函数包括 max, min, mean, median, std, var, sum, quantile ,其中分位数计算是全局方法,因此不能通过 array.quantile 的方法调用:
target = np.arange(5)
np.quantile(target, 0.5) # 0.5分位数
#2.0
#但是对于含有缺失值(nan)的数组,它们返回的结果也是缺失值,如果需要略过缺失值,必须使用 nan* 类型的函数,直接在几个统计函数前加nan。
target = np.array([1, 2, np.nan])
target.max()
# nan
np.nanmax(target)
# 2.0
#对于协方差和相关系数分别可以利用 cov, corrcoef 如下计算:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值