第5 章
Pandas 数据获取与清洗
对于数据分析而言,数据大部分来源于外部数据,如常用的CSV 文件、Excel文件和数
据库文件等。Pandas库将外部数据转换为DataFrame数据格式,处理完成后再存储到相应
的外部文件中。
前期采集到的数据,或多或少都存在一些瑕疵和不足,如数据缺失、极端值、数据格式不
统一等问题。数据预处理不仅可以提高初始数据的质量,保留与分析目标联系紧密的数据,
而且可以优化数据的表现形式,有助于提高数据分析或数据挖掘工作的效率和准确率。
数据清洗主要是将“脏”数据变成“干净”数据的过程,该过程中会通过一系列的方法对
“脏”数据进行处理,以达到清除冗余数据、规范数据、纠正错误数据的目的。
接下来,本节将针对Pandas中数据获取、清洗与格式化处理的内容进行详细讲解。
5.1 数据获取操作
在对数据进行分析时,通常不会将需要分析的数据直接写入程序中,这样不仅造成程序
代码臃肿,而且可用率很低。常用的方法是将需要分析的数据存储到本地,之后再对存储文
件进行读取。
初始数据获取是预处理的第一步,该步骤主要负责从文件、数据库、网页等众多渠道中
获取数据,以得到预处理的初始数据,为后续的处理工作做好数据准备。
针对不同的存储文件,Pandas读取数据的方式是不同的。Pandas将数据加载到
DataFrame后,就可以使用DataFrame对象的属性和方法进行操作。这些操作有的是完成
数据分析中的常规统计工作,有的是对数据的加工处理。
接下来,本节将针对常用存储格式文件的读写进行介绍。
5.1.1 读取文本(CSV 和TXT)文件
文本文件是一种由若干行字符构成的计算机文件,它是一种典型的顺序文件。CSV
(Comma-SeparatedValues)是一种逗号分隔的文件格式,因为其分隔符不一定是逗号,又被
称为字符分隔文件,文件以纯文本形式存储表格数据(数字和文本)。CSV 不仅可以是一个
实体文件,还可以是字符形式(如URL+data.csv),以便于在网络上传输。
CSV 文件是一种纯文本文件,可以使用任何文本编辑器进行编辑,它支持追加模式,节
省内存开销。因为CSV 文件具有诸多的优点,所以在很多时候会将数据保存到CSV 文
件中。
CSV 不带数据样式,标准化较强,是最为常见的数据格式。
1 24 Python 大数据分析与可视化
Pandas中提供了read_csv()函数用于读取CSV 文件,关于它们的具体介绍如下。
1.通过read_csv()函数读取CSV 文件的数据
read_csv()函数的作用是将CSV 文件的数据读取出来,并转换成DataFrame对象。
read_csv()函数的语法格式如下。
read_csv(filepath_or_buffer,sep= ',', delimiter= None, header= 'infer', names=
None, index_col=None, usecols=None, prefix=None,nrows=None, …)
参数说明如下。
.filepath_or_buffer:表示文件路径,可以为URL字符串。没有默认值,也不能为空,
根据Python的语法,第一个参数传参时可以不写参数名。
.sep:接收string,代表每行数据内容的分隔符。read_csv默认为“,”,read_table默
认为制表符“[Tab]”,如果分隔符指定错误,在读取数据的时候,每一行数据将连成
一片。read_csv()函数还提供了一个参数名为delimiter的定界符,这是一个备选分
隔符,是sep的别名,效果和sep一样。如果指定该参数,则sep参数失效。常见参
数的有以下形式。
pd.read_csv(r'./data.csv',sep='\t') #指定制表符分隔Tab
pd.read_csv(r'./data.csv',sep='(? 标签表格数据解析
为DataFrame。如返回有多个df的列表,则可以通过索引指定取第几个。如果页面里只有
一个表格,那么这个列表就只有一个DataFrame。
read_html()函数的语法格式如下。
pandas.read_html(io, match='.+', flavor=None,
header=None, index_col=None,skiprows=None, encoding=None,attrs=None)
参数说明如下。
.io:字符串,文件路径,也可以是URL链接。如果网址不接受https,可以尝试去掉
https中的s后爬取。
1 30 Python 大数据分析与可视化
. match:正则表达式,返回与正则表达式匹配的表格。
.flavor:解析器默认为“lxml”。
. header:指定列标题所在的行,列表list为多重索引。
.index_col:指定行标题对应的列,列表list为多重索引。
.encoding:字符串,默认为None,文件的编码格式。
.attrs:默认为None,用于表示表格的属性值。
在使用read_html()函数时,首先要确定网页表格是否为
标签。可以通过在
网页中单击右键,在弹出的菜单中选择“查看源文件”,查看代码是否含有表格标签“”的字样,然后才使用read_html()函数。
【例5-7】 读取新浪网上的大学部分专业信息。
import pandas as pd
import requests
html_ data = requests. get ( ' http://kaoshi. edu. sina. com. cn/college/majorlist?
page=1')
html_table_data = pd.read_html(html_data.content,header=0,encoding='utf-8')
columns = ['专业名称','专业代码','专业大类','专业小类']
df = pd.DataFrame(data=html_table_data[1],columns=columns)
print(df.head())
运行结果:
专业名称专业代码专业大类专业小类
0 哲学类101 哲学哲学类
1 哲学10101 哲学哲学类
2 逻辑学10102 哲学哲学类
3 宗教学10103 哲学哲学类
4 伦理学10104 哲学哲学类
值得一提的是,在使用read_html()函数读取网页中的表格数据时,需要注意网页的编
码格式。运行程序,如果出现“ImportError:lxmlnotfound,pleaseinstallit”的错误提示信
息,则需要安装lxml模块。
5.1.5 读取MySQL 数据库中数据
大多数情况下,海量的数据是使用数据库进行存储的,这主要是依赖于数据库的数据结
构化、数据共享性、独立性等特点。因此,在实际生产环境中,绝大多数的数据都是存储在数
据库中。
Pandas支持MySQL、Oracle、SQLite等主流数据库的读写操作。
为了高效地对数据库中的数据进行读取,这里需要引入SQLAlchemy。SQLAlchemy
是使用Python编写的一款开源软件,它提供的SQL工具包和对象映射工具能够高效地访
问数据库。在使用SQLAlchemy时需要使用相应的连接工具包,如MySQL 需要安装
mysqlconnector,Oracle则需要安装cx_oracle。
Pandas的io.sql模块中提供了常用的读写数据库函数,read_sql_table()函数与read_
sql_query()函数都可以将读取的数据转换为DataFrame对象,前者表示将整张表的数据转
换成DataFrame,后者则表示将执行SQL语句的结果转换为DataFrame对象。而read_sql()
第5 章 Pandas 数据获取与清洗1 31
函数同时支持read_sql_table()函数与read_sql_query()函数两者的功能。to_sql()方法则
是把记录数据写到数据库里。
在连接MySQL数据库时,这里使用的是mysqlconnector驱动,如果当前的Python环
境中没有该模块,则需要使用pipinstallmysql-connector命令安装该模块。下面以read_
sql()函数和to_sql()方法为例,分别介绍如何读写数据库中的数据,具体内容如下。
1.使用read_sql()函数读取数据
read_sql()函数既可以读取整张数据表,又可以执行SQL语句,其语法格式如下。
pandas.read_sql(sql,con,index_col= None,coerce_float= True,params= None,parse_
dates=None, columns=None, chunksize=None)
参数说明如下。
.sql:表示被执行的SQL语句。
.con:接收数据库连接,表示数据库的连接信息。
.index_col:默认为None,如果传入一个列表,则表示为层次化索引。
.coerce_float:将非字符串、非数字对象的值转换为浮点数类型。
. params:传递给执行方法的参数列表,如params={'name':'value'}。
.columns:接收list表示读取数据的列名,默认为None。
如果发现数据中存在空值,则会使用NaN 进行补全。
【例5-8】 使用read_sql()函数读取数据库中的数据表specialty。
import pandas as pd
from sqlalchemy import create_engine
#mysql 账号为root,密码为123456,数据名为jxgl
#数据表名称:specialty
engine = create_engine('mysql+pymysql://'
'root:123456@127.0.0.1:3306/jxgl')
#通过数据表名读取数据库的数据
#category_data = pd.read_sql('specialty', engine)
#也可以通过SQL 语句读取数据库的数据
sql = 'SELECT * FROM specialty'
df_data = pd.read_sql(sql, engine)
print(df_data)
运行结果:
zno zname
0 1102 数据科学与大数据技术
1 1103 人工智能
2 1201 网络与新媒体
3 1214 区块链科学与工程
4 1407 健康服务与管理
5 1409 智能医学工程
6 1601 供应链管理
7 1805 智能感知工程
8 1807 智能装备与系统
上述示例中,首先导入了sqlalchemy模块,通过create_engine()函数创建连接数据库
的信息,然后调用read_sql()函数读取数据库中的specialty数据表,并转换成DataFrame
对象。
1 32 Python 大数据分析与可视化
注意:在使用create_engine()函数创建连接时,其格式如下:'数据库类型+数据库驱
动名称://用户名:密码@机器地址:端口号/数据库名'。
需要强调的是,这里的SQL语句不仅是用于筛选的SQL语句,其他用于增删改查的
SQL语句都是可以执行的。
2.使用to_sql()方法将数据写入数据库中
to_sql()方法的功能是将Series或DataFrame对象以数据表的形式写入数据库中,其
语法格式如下。
to_sql(name, con, schema = None, if_exists = 'fail', index = True, index_label =
None,chunksize = None,dtype = None)
参数说明如下。
. name:表示数据库表的名称。
.con:表示数据库的连接信息。
.if_exists:可以取值为fail、replace或append,默认为fail。每个取值代表的含义
如下。
fail:如果表存在,则不执行写入操作。
replace:如果表存在,则将源数据库表删除再重新创建。
append:如果表存在,那么在原数据库表的基础上追加数据。
.index:表示是否将DataFrame行索引作为数据传入数据库,默认为True。
.index_label:表示是否引用索引名称。如果index设为True,此参数为None,则使
用默认名称;如果index为层次化索引,则必须使用序列类型。
接下来,通过一个示例程序来演示如何使用Pandas向数据库中写入数据。
首先,创建一个名称为students_info的数据库,具体的SQL语句如下。
CREATE DATABASE students_info CHARASET=utf8
然后,创建一个DataFrame对象,它统计了每个年级中男生和女生的人数。
接着,调用to_sql()方法将DataFrame对象写入名称为students的数据表中,具体代码
如下。
from pandas import DataFrame,Series
import pandas as pd
from sqlalchemy import create_engine
from sqlalchemy.types import *
df = DataFrame({"班级":["一年级","二年级","三年级","四年级"],
"男生人数":[25,23,27,30],
"女生人数":[19,17,20,20]})
#创建数据库引擎
#mysql+pymysql 表示使用MySQL 数据库的pymysql 驱动
#账号:root,密码:123456,数据库名:studnets_info
#数据表的名称: students
engine=create_engine('mysql+ mysqlconnector://root:123456@127.0.0.1/students_
info')
df.to_sql('students',engine)
当程序执行结束后,可以在数据库中查看是否成功创建了数据表,以及数据是否保存成
功,这里使用命令行的方式进行验证。