美文网首页简书Pythonpython初学者Python
Pandas从入门到精通(1)- 基础

Pandas从入门到精通(1)- 基础

作者: 木头里有虫911 | 来源:发表于2020-12-16 22:17 被阅读0次

    我们都知道Python之所有能在数据科学领域占有一席之地,主要是数据分析三剑客:numpy、pandas、matplotlib这三个库的功劳。而在这三个库中,我觉得最核心,用的最多的还是pandas。不管是在平时处理数据还是打比赛中,都要求能够对pandas进行熟练的应用。基于此,笔者参加了Datawhale开源社区组织的Pandas学习,目标就是爆肝一个月,精通Pandas!

    从本期开始,我们就开始来系统学习并梳理一下Pandas的知识。我们将按照下面的大纲分10期进行。我相信通过通过10期丰富的案例学习,掌握并熟练运用Pandas,水到渠成。

    • Pandas基础
    • 索引
    • 分组
    • 变形
    • 连接
    • 缺失数据
    • 文本数据
    • 分类数据
    • 时序数据
    • 综合练习

    本期作为第一期,主要是熟悉一些基础知识,为后期的学习做准备。主要包括Python中的一些常用函数和numpy库的一些操作。

    1.1 列表推导式

    列表推导式是Python语言的一大特色,可以快速简洁的创建列表。

    1.1.1 基本格式:

    [* for i in k]: * 可以是一个函数,变量为i(也可以与i无关),k为一个可迭代对象,如列表。
    应用: 1. 一句代码输出一个1到5的立方

    1. 一句代码创建一个列表,包含10个60-100的随机整数
    # 一句代码输出一个1到5的立方
    [i**3 for i in range(1,6)]
    >>>[1, 8, 27, 64, 125]
    # 一句代码创建一个列表,包含10个60-100的随机整数(模拟学生成绩)
    import random
    [random.randint(60,100) for _ in range(10)]
    >>> [76, 89, 62, 83, 61, 80, 89, 99, 76, 78]
    

    1.1.2 for循环嵌套

    列表推导式中的for循环支持嵌套功能。
    举例: 现有3个列表分别保存了顾客的姓名,衣服的颜色,尺码,用一句代码输出所有顾客和衣服颜色尺码的组合

    names = ['zhangsan', 'lisi', 'wangba']
    color = ['red', 'yellow']
    size = ['S', 'M', 'L']
    [name + '-' + c + '-' + s for name in names for c in color for s in size]
    >>>
    ['zhangsan-red-S',
     'zhangsan-red-M',
     'zhangsan-red-L',
     'zhangsan-yellow-S',
     'zhangsan-yellow-M',
     'zhangsan-yellow-L',
     'lisi-red-S',
     'lisi-red-M',
     'lisi-red-L',
     'lisi-yellow-S',
     'lisi-yellow-M',
     'lisi-yellow-L',
     'wangba-red-S',
     'wangba-red-M',
     'wangba-red-L',
     'wangba-yellow-S',
     'wangba-yellow-M',
     'wangba-yellow-L']
    

    上面的代码等价于:

    for name in names:
        for c in color:
            for s in size:
                print(name + '-' + c + '-' + 's')
    >>>
    zhangsan-red-s
    zhangsan-red-s
    zhangsan-red-s
    zhangsan-yellow-s
    zhangsan-yellow-s
    zhangsan-yellow-s
    lisi-red-s
    lisi-red-s
    lisi-red-s
    lisi-yellow-s
    lisi-yellow-s
    lisi-yellow-s
    wangba-red-s
    wangba-red-s
    wangba-red-s
    wangba-yellow-s
    wangba-yellow-s
    wangba-yellow-s
    

    1.1.3 筛选功能

    列表推导式中for循环后还可以加入if (或者if...else...)进行筛选 。
    举例: 一句代码输出0-100内可以被7整除的整数

    # 输出1-100内可以被7整除的数:
    [i for i in range(1,101) if i%7 == 0]
    >>>
    [7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98]
    

    综合上面的案例,我们可以清晰的看到列表推导式的简洁与优雅!同时也体现Python的强大之处。

    1.2 lambda匿名函数

    我们都知道函数在python世界中属于一等公民,具有很高的权限。对于经常需要重复使用的代码块,一般都要优先考虑通过函数来实现。但是当我们想要使用一个简单定义的,或者只需要调用一两次的函数时,取名并编写一个完整的函数块就显得多余。这时候lambda匿名函数就有了用武之地。
    格式: lambda [arg1 [,arg2, ... argN]] : expression
    这里的lamdbda是系统保留的关键字, [arg1 [,arg2, ... argN]]是参数列表,它的结构与Python中函数(function)的参数列表是一样的。expression是一个关于参数的表达式。表达式中出现的参数需要在argument_list中有定义,并且表达式只能是单行的。
    举例:例如我们定义一个函数,将字符串中的所有字母大写输出

    def str_capital(s):
        return str.upper(s)
    
    str_capital('datawhale')
    >>>
    'DATAWHALE'
    

    如果改用匿名函数的写法:

    upper = lambda x: str.upper(x)
    upper('datawhale')
    >>>
    'DATAWHALE'
    

    对比一下可以看到匿名函数有如下优点:

    • 可以直接在使用的地方定义,如果需要修改,直接找到修改即可,方便以后代码的维护工作
    • 语法结构简单,不用使用def 函数名(参数名):这种方式定义,直接使用lambda 参数:返回值 定义即可
      但是需要注意的是lambda匿名函数让程序简洁,但是并不能让程序高效,这个也是很多程序员反对使用lambda的原因。

    1.3 map()方法

    在Python中,匿名函数lambda经常和map()、reduce()和filter()三个应用于序列的内置函数联合使用,用于对序列进行遍历、递归计算以及筛选。这其中,最常用的就是map方法。在Python中,map()函数的本质是一种映射,即对输入其中的可迭代对象(列表)中每个元素执行定义的映射。例如我们编写了一个将给定的字符串大写输出的函数,在使用该函数将若干字符串大写输出

    def str_capital(s):
        return str.upper(s)
    L1 = ['I', 'like', 'Datawhale']
    L2 = []
    for s in L1:
        L2.append(str_capital(s))
    L2
    >>> 
    ['I', 'LIKE', 'DATAWHALE']
    

    如果我们用map()替代for循环:

    L3 = map(str_capital, L1)
    list(L3)
    >>>
    ['I', 'LIKE', 'DATAWHALE']
    

    可以看到更加简洁!需要注意的是map()方法返回的是一个map()对象,需要用list()方法输出其中的元素。上面我们说了map经常和lambda匿名函数结合使用,如下:

    L4 = map(lambda x: str.upper(x), L1)
    list(L4)
    >>>
    ['I', 'LIKE', 'DATAWHALE']
    

    优雅!

    1.4 zip方法

    我们都知道zip是一个文件解压程序,同样的,在python中zip()函数就有点类似于解压缩包的感觉:传入一个列表或者其他可迭代对象,依次从中选取一个组成新的元组输出。下面举例:

    a = [3,4,5,6]
    b = ['a', 'b', 'c']
    s1 = {'zhangsan': 20, 'lisi': 25}
    print(zip(a))
    print('*' * 10)
    print(list(zip(a)))
    print(list(zip(b)))
    print(list(zip(s1)))
    >>>
    <zip object at 0x000001A7D4FF7940>
    **********
    [(3,), (4,), (5,), (6,)]
    [('a',), ('b',), ('c',)]
    [('zhangsan',), ('lisi',)]
    

    可以看到zip的输出也是一个zip对象,需要用list查看其中的元素。
    当zip()函数有两个参数时 ,如zip(a,b),则分别从a和b依次各取出一个元素组成元组,再将依次组成的元组组合成一个新的迭代器。如:

    print(list(zip(a,b)))
    >>>
    [(3, 'a'), (4, 'b'), (5, 'c')]
    

    这样设计有个特殊的用途,用于矩阵(二维数组)的加减和点乘,举例如下:

    import numpy as np
    m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    n = [[2, 2, 2], [3, 3, 3], [4, 4, 4]]
    # 矩阵点乘
    print('=*'*10 + "矩阵点乘" + '=*'*10)
    print(np.array([x*y for a, b in zip(m, n) for x, y in zip(a, b)]).reshape(3,3))
    # 矩阵相加,相减雷同
    print('=*'*10 + "矩阵相加,相减" + '=*'*10)
    print(np.array([x+y for a, b in zip(m, n) for x, y in zip(a, b)]).reshape(3,3))
    >>>
    =*=*=*=*=*=*=*=*=*=*矩阵点乘=*=*=*=*=*=*=*=*=*=*
    [[ 2  4  6]
     [12 15 18]
     [28 32 36]]
    =*=*=*=*=*=*=*=*=*=*矩阵相加,相减=*=*=*=*=*=*=*=*=*=*
    [[ 3  4  5]
     [ 7  8  9]
     [11 12 13]]
    

    知识链接:矩阵点乘
    矩阵点乘: 对应元素相乘,要求两个矩阵的形状必须相同。这个要和矩阵叉乘区分开来。

    2. Numpy复习回顾

    pandas是基于numpy来实现高效计算的,因而在学习pandas之前有必要先把之前学习的numpy的知识温习一下,这里总结了一些numpy一些常用的知识点

    2.1 np.array

    np里面最基本的数据结构是array(数组),构造也非常简单,np.array即可。下面总结几种特殊的array

    1. 等差序列
    • np.linspace(起始,终止(包含),样本个数): 适用于提前知道需要创建多少个样本的情况
    • np.arange(起始,终止(不包含),步长): 适用于提前知道相邻间隔的情况
      注意 np.arange和python数组中的range不要混淆了。range只能生成整数数列,而np.arange可以生成小数数列
    import numpy as np
    a = np.linspace(1,100,10)
    b = np.arange(1,10,1.5)
    print(a)
    print(b)
    >>>
    [  1.  12.  23.  34.  45.  56.  67.  78.  89. 100.]
    [1.  2.5 4.  5.5 7.  8.5]
    
      1. 特殊矩阵,包括zeros/ones/eye/full等
        直接上代码参考:
    print('3行4列全0矩阵')
    print(np.zeros((3,4)))
    print('*' * 10)
    print('3行3列全1矩阵')
    print(np.ones((3, 3)))
    print('*' * 10)
    print('3行3列的单位矩阵')
    print(np.eye(3))
    print('*' * 10)
    print('指定维度的/数值填充矩阵')
    print(np.full((2,3), 6))
    >>>
    3行4列全0矩阵
    [[0. 0. 0. 0.]
     [0. 0. 0. 0.]
     [0. 0. 0. 0.]]
    **********
    3行3列全1矩阵
    [[1. 1. 1.]
     [1. 1. 1.]
     [1. 1. 1.]]
    **********
    3行3列的单位矩阵
    [[1. 0. 0.]
     [0. 1. 0.]
     [0. 0. 1.]]
    **********
    指定维度的/数值填充矩阵
    [[6 6 6]
     [6 6 6]]
    
      1. 随机矩阵
    • np.random.rand() : 取值0-1之间的随机分布,这里不要传元组,直接指定不同维度的个数即可
    • np.random.randn(): 0~1标准正态分布
    • np.random.randint(low,high,size) :指定生成随机整数的最小值最大值和维度大小
    • np.random.choice(): 可以从给定的列表中,以一定概率和方式抽取结果,当不指定概率时为均匀采样,默认抽取方式为有放回抽样
    • np.random.seed(0) : 设置种子,就相当是设定了随机值,之后每次随机都一样

    2. 练习题:

    1. 使用列表推导式完成矩阵乘法:
      矩阵乘法定义:


      image.png

      一般的矩阵乘法根据公式,可以由三重循环写出:


      image.png

    使用列表推导式来替代for循环完成

    # 先定义零个矩阵
    M1 = np.random.randint(1,10,10).reshape(2,5)
    M2 = np.random.randint(1,10,10).reshape(5,2)
    print(M1)
    print('-' * 5)
    print(M2)
    M1@M2 # 矩阵乘法
    >>>
    [[6 1 2 8 5]
     [6 1 7 9 4]]
    -----
    [[6 2]
     [7 7]
     [1 4]
     [7 1]
     [8 3]]
    array([[141,  50],
           [145,  68]])
    # 使用列表推导式来完成
    [[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])]
    >>>
    [[141, 50], [145, 68]]
    
    1. 更新矩阵
      设矩阵 Am×n ,现在对 A 中的每一个元素进行更新生成矩阵 B ,更新方法是


      image.png

    例如下面的矩阵为 A ,则 B_{2,2}=5×(1/4+1/5+1/6)=37/12 ,请利用 Numpy 高效实现。

    image.png

    解答:

    A = np.arange(1,10).reshape(3,3)
    B = A*(1/A).sum(1).reshape(-1,1)
    
    image.png

    使用内置的函数

    B = A.sum(0) * A.sum(1).reshape(-1,1) / A.sum()
    print(B)
    res = ((A-B) ** 2 / B).sum()
    print(res)
    

    参考:开源内容Joyful Pandas, 作者 DataWhale耿远昊
    另外,更多精彩内容也可以微信搜索,并关注公众号:‘Python数据科学家之路“ ,期待您的到来和我交流

    相关文章

      网友评论

        本文标题:Pandas从入门到精通(1)- 基础

        本文链接:https://www.haomeiwen.com/subject/ydlngktx.html