CodeRoadMap
路线图学习路径文章题库资源社区

浏览

首页路线图学习路径知识库题库文章资源社区我的学习
CodeRoadMap

中文编程学习导航:路线图、讲义与题库,进度可同步。

路线图学习路径文章题库社区

© 2026 CodeRoadMap

津ICP备2026012044号-1|coderoadmap@126.com
首页/Python 100 天/73.深入浅出pandas-2

课程目录

  1. 0101.初识Python
  2. 0202.第一个Python程序
  3. 0303.Python语言中的变量
  4. 0404.Python语言中的运算符
  5. 0505.分支结构
  6. 0606.循环结构
  7. 0707.分支和循环结构实战
  8. 0808.常用数据结构之列表-1
  9. 0909.常用数据结构之列表-2
  10. 1010.常用数据结构之元组
  11. 1111.常用数据结构之字符串
  12. 1212.常用数据结构之集合
  13. 1313.常用数据结构之字典
  14. 1414.函数和模块
  15. 1515.函数应用实战
  16. 1616.函数使用进阶
  17. 1717.函数高级应用
  18. 1818.面向对象编程入门
  19. 1919.面向对象编程进阶
  20. 2020.面向对象编程应用
  21. 2121.文件读写和异常处理
  22. 2222.对象的序列化和反序列化
  23. 2323.Python读写CSV文件
  24. 2424.Python读写Excel文件-1
  25. 2525.Python读写Excel文件-2
  26. 2626.Python操作Word和PowerPoint文件
  27. 2727.Python操作PDF文件
  28. 2828.Python处理图像
  29. 2929.Python发送邮件和短信
  30. 3030.正则表达式的应用
  31. 3131.Python语言进阶
  32. 3232-33.Web前端入门
  33. 3334-35.玩转Linux操作系统
  34. 3436.关系型数据库和MySQL概述
  35. 3537.SQL详解之DDL
  36. 3638.SQL详解之DML
  37. 3739.SQL详解之DQL
  38. 3840.SQL详解之DCL
  39. 3941.MySQL新特性
  40. 4042.视图、函数和过程
  41. 4143.索引
  42. 4244.Python接入MySQL数据库
  43. 4345.Hive实战
  44. 4446.Django快速上手
  45. 4547.深入模型
  46. 4648.静态资源和Ajax请求
  47. 4749.Cookie和Session
  48. 4850.制作报表
  49. 4951.日志和调试工具栏
  50. 5052.中间件的应用
  51. 5153.前后端分离开发入门
  52. 5254.RESTful架构和DRF入门
  53. 5355.RESTful架构和DRF进阶
  54. 5456.使用缓存
  55. 5557.接入三方平台
  56. 5658.异步任务和定时任务
  57. 5759.单元测试
  58. 5860.项目上线
  59. 5961.网络数据采集概述
  60. 6062.用Python获取网络资源-1
  61. 6162.用Python解析HTML页面-2
  62. 6263.并发编程在爬虫中的应用
  63. 6363.Python中的并发编程-1
  64. 6463.Python中的并发编程-2
  65. 6563.Python中的并发编程-3
  66. 6664.使用Selenium抓取网页动态内容
  67. 6765.爬虫框架Scrapy简介
  68. 6866.数据分析概述
  69. 6967.环境准备
  70. 7068.NumPy的应用-1
  71. 7169.NumPy的应用-2
  72. 7270.NumPy的应用-3
  73. 7371.NumPy的应用-4
  74. 7472.深入浅出pandas-1
  75. 7573.深入浅出pandas-2
  76. 7674.深入浅出pandas-3
  77. 7775.深入浅出pandas-4
  78. 7876.深入浅出pandas-5
  79. 7977.深入浅出pandas-6
  80. 8078.数据可视化-1
  81. 8179.数据可视化-2
  82. 8280.数据可视化-3
  83. 8381.浅谈机器学习
  84. 8482.k最近邻算法
  85. 8583.决策树和随机森林
  86. 8684.朴素贝叶斯算法
  87. 8785.回归模型
  88. 8886.K-Means聚类算法
  89. 8987.集成学习算法
  90. 9088.神经网络模型
  91. 9189.自然语言处理入门
  92. 9290.机器学习实战
  93. 9391.团队项目开发的问题和解决方案
  94. 9492.Docker容器技术详解
  95. 9593.MySQL性能优化
  96. 9694.网络API接口设计
  97. 9795.使用Django开发商业项目
  98. 9896.软件测试和自动化测试
  99. 9997.电商网站技术要点剖析
  100. 10098.项目部署上线和性能调优
  101. 10199.面试中的公共问题
  102. 102100.补充内容
第 75 课1 天

73.深入浅出pandas-2

如果使用 pandas 做数据分析,那么DataFrame一定是被使用得最多的类型,它可以用来保存和处理异质的二维数据。这里所谓的“异质”是指DataFrame

课程内容

深入浅出pandas-2

如果使用 pandas 做数据分析,那么DataFrame一定是被使用得最多的类型,它可以用来保存和处理异质的二维数据。这里所谓的“异质”是指DataFrame中每个列的数据类型不需要相同,这也是它区别于 NumPy 二维数组的地方。DataFrame提供了极为丰富的属性和方法,帮助我们实现对数据的重塑、清洗、预处理、透视、呈现等一系列操作。

创建DataFrame对象

通过二维数组创建DataFrame对象

代码:

scores = np.random.randint(60, 101, (5, 3))
courses = ['语文', '数学', '英语']
stu_ids = np.arange(1001, 1006)
df1 = pd.DataFrame(data=scores, columns=courses, index=stu_ids)
df1

输出:

        语文  数学  英语
1001    69    80    79
1002    71    60    100
1003    94    81    93
1004    88    88    67
1005    82    66    60

通过字典创建DataFrame对象

代码:

scores = {
    '语文': [62, 72, 93, 88, 93],
    '数学': [95, 65, 86, 66, 87],
    '英语': [66, 75, 82, 69, 82],
}
stu_ids = np.arange(1001, 1006)
df2 = pd.DataFrame(data=scores, index=stu_ids)
df2

输出:

        语文  数学  英语
1001    62    95    66
1002    72    65    75
1003    93    86    82
1004    88    66    69
1005    93    87    82

读取CSV文件创建DataFrame对象

可以通过pandas 模块的read_csv函数来读取 CSV 文件,read_csv函数的参数非常多,下面介绍几个比较重要的参数。

  • sep / delimiter:分隔符,默认是,。
  • header:表头(列索引)的位置,默认值是infer,用第一行的内容作为表头(列索引)。
  • index_col:用作行索引(标签)的列。
  • :需要加载的列,可以使用序号或者列名。
usecols
  • true_values / false_values:哪些值被视为布尔值True / False。
  • skiprows:通过行号、索引或函数指定需要跳过的行。
  • skipfooter:要跳过的末尾行数。
  • nrows:需要读取的行数。
  • na_values:哪些值被视为空值。
  • iterator:设置为True,函数返回迭代器对象。
  • chunksize:配合上面的参数,设置每次迭代获取的数据体量。
  • 代码:

    df3 = pd.read_csv('data/2018年北京积分落户数据.csv', index_col='id')
    df3
    

    提示:上面代码中的CSV文件是用相对路径进行获取的,也就是说当前工作路径下有名为data的文件夹,而“2018年北京积分落户数据.csv”就在这个文件夹下。如果使用Windows系统,在写路径分隔符时也建议使用/而不是\,如果想使用\,建议在字符串前面添加一个r,使用原始字符串来避开转义字符,例如r'c:\new\data\2018年北京积分落户数据.csv'。

    输出:

          name   birthday      company          score
    id                                             
    1     杨xx   1972-12       北京利德华福xxxx  122.59
    2     纪xx   1974-12       北京航天数据xxxx  121.25
    3     王x    1974-05       品牌联盟(北京)xx  118.96
    4     杨x    1975-07       中科专利商标xxxx  118.21
    5     张xx   1974-11       北京阿里巴巴xxxx  117.79
    ...   ...      ...                  ...     ...
    6015  孙xx   1978-08       华为海洋网络xxxx   90.75
    6016  刘xx   1976-11       福斯(上海)xxxx   90.75
    6017  周x    1977-10       赢创德固赛xxxxxx   90.75
    6018  赵x    1979-07       澳科利耳医疗xxxx   90.75
    6019  贺x    1981-06       北京宝洁技术xxxx   90.75
    
    [6019 rows x 4 columns]
    

    说明: 上面输出的内容隐去了姓名(name)和公司名称(company)字段中的部分信息。如果需要上面例子中的 CSV 文件,可以通过百度云盘获取,链接:<https://pan.baidu.com/s/1rQujl5RQn9R7PadB2Z5g_g>,提取码:e7b4。

    读取Excel工作表创建DataFrame对象

    可以通过pandas 模块的read_excel函数来读取 Excel 文件,该函数与上面的read_csv非常类似,多了一个sheet_name参数来指定数据表的名称,但是不同于 CSV 文件,没有sep或delimiter这样的参数。假设有名为“2022年股票数据.xlsx”的 Excel 文件,里面有用股票代码命名的五个表单,分别是阿里巴巴(BABA)、百度(BIDU)、京东(JD)、亚马逊(AMZN)、甲骨文(ORCL)这五个公司2022年的股票数据,如果想加载亚马逊的股票数据,代码如下所示。

    代码:

    df4 = pd.read_excel('data/2022年股票数据.xlsx', sheet_name='AMZN', index_col='Date')
    df4
    

    说明:上面例子中的 CSV 文件可以通过百度云盘获取,链接:<https://pan.baidu.com/s/1rQujl5RQn9R7PadB2Z5g_g>,提取码:e7b4。

    输出:

                   Open     High       Low    Close    Volume
    Date                                                     
    2022-12-30   83.120   84.050   82.4700   84.000  62401194
    2022-12-29   82.870   84.550   82.5500   84.180  54995895
    2022-12-28   82.800   83.480   81.6900   81.820  58228575
    2022-12-27   84.970   85.350   83.0000   83.040  57284035
    2022-12-23   83.250   85.780   82.9344   85.250  57433655
    ...             ...      ...       ...      ...       ...
    2022-01-07  163.839  165.243  162.0310  162.554  46605900
    2022-01-06  163.450  164.800  161.9370  163.254  51957780
    2022-01-05  166.883  167.126  164.3570  164.357  64302720
    2022-01-04  170.438  171.400  166.3490  167.522  70725160
    2022-01-03  167.550  170.704  166.1600  170.404  63869140
    
    [251 rows x 5 columns]
    

    读取关系数据库二维表创建DataFrame对象

    pandas模块的read_sql函数可以通过 SQL 语句从数据库中读取数据创建DataFrame对象,该函数的第二个参数代表了需要连接的数据库。对于 MySQL 数据库,我们可以通过pymysql或mysqlclient来创建数据库连接(需要提前安装好三方库),得到一个Connection 对象,而这个对象就是read_sql函数需要的第二个参数,代码如下所示。

    代码:

    import pymysql
    
    # 创建一个MySQL数据库的连接对象
    conn = pymysql.connect(
        host='101.42.16.8', port=3306,
        user='guest', password='Guest.618',
        database='hrs', charset='utf8mb4'
    )
    # 通过SQL从数据库二维表读取数据创建DataFrame
    df5 = pd.read_sql('select * from tb_emp', conn, index_col='eno')
    df5
    

    提示:执行上面的代码需要先安装pymysql库,如果尚未安装,可以先在单元格中先执行魔法指令%pip install pymysql,然后再运行上面的代码。上面的代码连接的是我部署在腾讯云上的 MySQL 数据库,公网 IP 地址:101.42.16.8,用户名:guest,密码:Guest.618,数据库:hrs,字符集:utf8mb4,大家可以使用这个数据库,但是不要进行恶意的访问。hrs数据库一共有三张表,分别是:tb_dept(部门表)、tb_emp(员工表)、tb_emp2(员工表2)。

    输出:

           ename   job     mgr     sal    comm    dno
    eno                                        
    1359   胡一刀   销售员  3344.0  1800   200.0   30
    2056    乔峰   分析师   7800.0  5000  1500.0   20
    3088   李莫愁   设计师  2056.0  3500   800.0   20
    3211   张无忌   程序员  2056.0  3200     NaN   20
    3233   丘处机   程序员  2056.0  3400     NaN   20
    3244   欧阳锋   程序员  3088.0  3200     NaN   20
    3251   张翠山   程序员  2056.0  4000     NaN   20
    3344    黄蓉  销售主管  7800.0  3000   800.0   30
    3577    杨过    会计    5566.0  2200     NaN   10
    3588   朱九真    会计   5566.0  2500     NaN   10
    4466   苗人凤   销售员  3344.0  2500     NaN   30
    5234    郭靖    出纳    5566.0  2000     NaN   10
    5566   宋远桥   会计师  7800.0  4000  1000.0   10
    7800   张三丰    总裁     NaN   9000  1200.0   20
    

    执行上面的代码会出现一个警告,因为 pandas 库希望我们使用SQLAlchemy三方库接入数据库,具体内容是:“UserWarning: pandas only supports SQLAlchemy connectable (engine/connection) or database string URI or sqlite3 DBAPI2 connection. Other DBAPI2 objects are not tested. Please consider using SQLAlchemy.”。如果不想看到这个警告,我们可以试一试下面的解决方案。

    首先,安装三方库SQLAlchemy,在 Jupyter 中可以使用%pip魔法指令。

    %pip install sqlalchemy
    

    通过SQLAlchemy的create_engine函数创建Engine对象作为read_sql函数的第二个参数,此时read_sql函数的第一个参数可以是 SQL 语句,也可以是二维表的表名。

    from sqlalchemy import create_engine
    
    # 通过指定的URL(统一资源定位符)访问数据库
    engine = create_engine('mysql+pymysql://guest:Guest.618@101.42.16.8:3306/hrs')
    # 直接通过表名加载整张表的数据
    df5 = pd.read_sql('tb_emp', engine, index_col='eno')
    df5
    

    说明:如果通过表名加载二维表数据,也可以将上面的函数换成read_sql_table。

    我们再来加载部门表的数据创建DataFrame对象。

    df6 = pd.read_sql('select dno, dname, dloc from tb_dept', engine, index_col='dno')
    df6
    

    说明:如果通过 SQL 查询获取数据,也可以将上面的函数换成read_sql_query。

    输出:

          dname   dloc
    dno           
    10    会计部   北京
    20    研发部   成都
    30    销售部   重庆
    40    运维部   深圳
    

    在完成数据加载后,如果希望释放数据库连接,可以使用下面的代码。

    engine.connect().close()
    

    基本属性和方法

    在开始讲解DataFrame的属性和方法前,我们先从之前提到的hrs数据库中读取三张表的数据,创建出三个DataFrame对象,完整的代码如下所示。

    from sqlalchemy import create_engine
    
    engine = create_engine('mysql+pymysql://guest:Guest.618@101.42.16.8:3306/hrs')
    dept_df = pd.read_sql_table('tb_dept', engine, index_col='dno')
    emp_df = pd.read_sql_table('tb_emp', engine, index_col='eno')
    emp2_df = pd.read_sql_table('tb_emp2', engine, index_col='eno')
    

    得到的三个DataFrame对象如下所示。

    部门表(dept_df),其中dno是部门的编号,dname和dloc分别是部门的名称和所在地。

        dname  dloc
    dno
    10  会计部  北京
    20  研发部  成都
    30  销售部  重庆
    40  运维部  深圳
    

    员工表(emp_df),其中eno是员工编号,ename、job、mgr、sal、comm和dno分别代表员工的姓名、职位、主管编号、月薪、补贴和部门编号。

            ename    job        mgr      sal     comm    dno
    eno
    1359    胡一刀    销售员      3344.0    1800    200.0    30
    2056    乔峰      分析师      7800.0    5000    1500.0   20
    3088    李莫愁    设计师      2056.0    3500    800.0    20
    3211    张无忌     程序员     2056.0    3200    NaN     20
    3233    丘处机     程序员     2056.0    3400    NaN     20
    3244    欧阳锋     程序员     3088.0    3200    NaN     20
    3251    张翠山     程序员     2056.0    4000    NaN     20
    3344    黄蓉      销售主管    7800.0    3000    800.0   30
    3577    杨过      会计       5566.0    2200     NaN     10
    3588    朱九真     会计       5566.0    2500    NaN     10
    4466    苗人凤     销售员     3344.0    2500    NaN     30
    5234    郭靖       出纳      5566.0    2000    NaN      10
    5566    宋远桥     会计师     7800.0    4000    1000.0   10
    7800    张三丰     总裁       NaN      9000    1200.0    20
    

    说明:在数据库中mgr和comm两个列的数据类型是int,但是因为有缺失值(空值),读取到DataFrame之后,列的数据类型变成了float,因为我们通常会用float类型的NaN来表示空值。

    员工表(emp2_df),跟上面的员工表结构相同,但是保存了不同的员工数据。

           ename    job      mgr      sal    comm    dno
    eno                                      
    9500   张三丰   总裁      NaN      50000  8000    20
    9600   王大锤   程序员    9800.0   8000   600     20
    9700   张三丰   总裁      NaN      60000  6000    20
    9800   骆昊     架构师    7800.0   30000  5000    20
    9900   陈小刀   分析师    9800.0   10000  1200    20
    

    DataFrame对象的属性如下表所示。

    属性名说明
    at / iat通过标签获取DataFrame中的单个值。
    columnsDataFrame对象列的索引
    dtypesDataFrame对象每一列的数据类型
    emptyDataFrame对象是否为空
    loc / iloc通过标签获取DataFrame中的一组值。
    ndimDataFrame对象的维度
    shapeDataFrame对象的形状(行数和列数)
    sizeDataFrame对象中元素的个数
    valuesDataFrame对象的数据对应的二维数组

    关于DataFrame的方法,首先需要了解的是info()方法,它可以帮助我们了解DataFrame的相关信息,如下所示。

    代码:

    emp_df.info()
    

    输出:

    <class 'pandas.core.frame.DataFrame'>
    Int64Index: 14 entries, 1359 to 7800
    Data columns (total 6 columns):
     #   Column  Non-Null Count  Dtype  
    ---  ------  --------------  -----  
     0   ename   14 non-null     object 
     1   job     14 non-null     object 
     2   mgr     13 non-null     float64
     3   sal     14 non-null     int64  
     4   comm    6 non-null      float64
     5   dno     14 non-null     int64  
    dtypes: float64(2), int64(2), object(2)
    memory usage: 1.3+ KB
    

    如果需要查看DataFrame的头部或尾部的数据,可以使用head()或tail()方法,这两个方法的默认参数是5,表示获取DataFrame最前面5行或最后面5行的数据,如下所示。

    emp_df.head()
    

    输出:

            ename    job    mgr    sal    comm  dno
    eno
    1359    胡一刀   销售员   3344   1800   200   30
    2056    乔峰     分析师   7800   5000   1500  20
    3088    李莫愁    设计师   2056   3500  800   20
    3211    张无忌    程序员   2056   3200  NaN   20
    3233    丘处机    程序员   2056   3400  NaN   20
    

    操作数据

    索引和切片

    如果要获取DataFrame的某一列,例如取出上面emp_df的ename列,可以使用下面的两种方式。

    emp_df.ename
    

    或者

    emp_df['ename']
    

    执行上面的代码可以发现,我们获得的是一个Series对象。事实上,DataFrame对象就是将多个Series对象组合到一起的结果。

    如果要获取DataFrame的某一行,可以使用整数索引或我们设置的索引,例如取出员工编号为2056的员工数据,代码如下所示。

    emp_df.iloc[1]
    

    或者

    emp_df.loc[2056]
    

    通过执行上面的代码我们发现,单独取DataFrame 的某一行或某一列得到的都是Series对象。我们当然也可以通过花式索引来获取多个行或多个列的数据,花式索引的结果仍然是一个DataFrame对象。

    获取多个列:

    emp_df[['ename', 'job']]
    

    获取多个行:

    emp_df.loc[[2056, 7800, 3344]]
    

    如果要获取或修改DataFrame 对象某个单元格的数据,需要同时指定行和列的索引,例如要获取员工编号为2056的员工的职位信息,代码如下所示。

    emp_df['job'][2056]
    

    或者

    emp_df.loc[2056]['job']
    

    或者

    emp_df.loc[2056, 'job']
    

    我们推荐大家使用第三种做法,因为它只做了一次索引运算。如果要将该员工的职位修改为“架构师”,可以使用下面的代码。

    emp_df.loc[2056, 'job'] = '架构师'
    

    当然,我们也可以通过切片操作来获取多行多列,相信大家一定已经想到了这一点。

    emp_df.loc[2056:3344]
    

    输出:

            ename    job        mgr      sal     comm    dno
    eno
    2056    乔峰      分析师     7800.0    5000    1500.0   20
    3088    李莫愁    设计师     2056.0    3500    800.0    20
    3211    张无忌    程序员     2056.0    3200    NaN      20
    3233    丘处机    程序员     2056.0    3400    NaN      20
    3244    欧阳锋    程序员     3088.0    3200    NaN      20
    3251    张翠山    程序员     2056.0    4000    NaN      20
    3344    黄蓉     销售主管    7800.0    3000    800.0    30
    

    数据筛选

    上面我们提到了花式索引,相信大家已经联想到了布尔索引。跟ndarray和Series一样,我们可以通过布尔索引对DataFrame对象进行数据筛选,例如我们要从emp_df中筛选出月薪超过3500的员工,代码如下所示。

    emp_df[emp_df.sal > 3500]
    

    输出:

            ename    job        mgr      sal     comm    dno
    eno
    2056    乔峰      分析师      7800.0   5000    1500.0    20
    3251    张翠山    程序员      2056.0    4000    NaN      20
    5566    宋远桥    会计师      7800.0    4000    1000.0   10
    7800    张三丰    总裁        NaN      9000    1200.0    20
    

    当然,我们也可以组合多个条件来进行数据筛选,例如从emp_df中筛选出月薪超过3500且部门编号为20的员工,代码如下所示。

    emp_df[(emp_df.sal > 3500) & (emp_df.dno == 20)]
    

    输出:

            ename    job        mgr      sal     comm    dno
    eno
    2056    乔峰      分析师      7800.0   5000   1500.0    20
    3251    张翠山     程序员     2056.0   4000    NaN       20
    7800    张三丰     总裁       NaN      9000   1200.0    20
    

    除了使用布尔索引,DataFrame对象的query方法也可以实现数据筛选,query方法的参数是一个字符串,它代表了筛选数据使用的表达式,而且更符合 Python 程序员的使用习惯。下面我们使用query方法将上面的效果重新实现一遍,代码如下所示。

    emp_df.query('sal > 3500 and dno == 20')
    
    ← 上一课72.深入浅出pandas-1下一课 →74.深入浅出pandas-3