Pandas是基于Numpy构建的、开源的Python数据分析工具包,借助高效的数据结构提供面向大规模数据的、高性能的数据分析操作。
Pandas有两种重要的数据结构,Series和DataFrame。熟悉这两种数据结构是熟练使用Pandas的前提。下面结合实例讲述这两种数据结构相关的知识内容,以及Pandas的用法。
我们将使用Jupyter Notebook来编写和运行代码下面列出的代码。这些代码涉及Pandas基本操作。首先,我们要做以下准备工作:
(1) 启动Jupyter Notebook。
(2) 单击进入一个文件夹(比如选择Desktop文件夹)。
(3) 新建一份交互式文档。
(4) 把文档命名为“Pandas-codes”。
(5) 在第1个代码输入框内敲入图所示的两行语句。这两行语句的作用是引入numpy模块,并把模块名字简写为“np”;引入pandas模块,并把模块名字简写为“pd”。
(6) 运行上述代码。如果页面上显示有“In [*]”,表明代码正在执行中,执行完后,方括号的星号将变为数字。
Jupyter Notebook的使用详述了以上步骤的具体做法。完成以上6个步骤后,浏览器内的Notebook页面如图所示。
使用Pandas前的准备工作
1. Series介绍
Series是带标签的一维ndarray。ndarray是Numpy的多维数组。所谓标签,有点类似于数据记录的主关键字,也类似于字典的键。下面的代码定义了名字为sd的变量,其类型是Series。
上述各行中,第2个代码输入框内的,也即“In [2]:”开头的输入框内的,第2行代码是从字典d生成Series变量sd。第二个参数指出字典的键用作sd变量的标签。“Out[2]:”开头的5行,也即最后5行,是sd变量的输出内容。每一行有两列,第1列是标签,第2列是元素值。例如,sd变量的第一个元素的标签是’d’字母,其值是2。
对于Series变量sd,有两种索引,第一种是位置索引。下面的代码通过位置索引访问了第一个元素。
第二种是标签索引。下面的代码通过标签索引访问了标签为a字母的元素。
下面的代码通过Series变量的iloc属性和位置索引访问了第一个元素。
下面的代码输出Series变量的index属性值。index属性值是标签索引。
2. DataFrame介绍
DataFrame是带有标签的二维表格。
下面的代码生成了5行3列的矩阵d5x3,它是Numpy的ndarray。
在d5x3矩阵的基础上,下面的2行代码生成了一个叫df5x3的DataFrame。其中第1行代码使用Pandas模块的DataFrame函数,从二维矩阵生成DataFrame。第二个参数指明DataFrame各列的字段名称依次是字母A、B、C。第2行代码输出df5x3的值。其后的6行正是df5x3的输出内容。
df5x3的输出内容一共6行4列。第1行是列标题。第1列是行索引。DataFrame有行标签和列标题,而Numpy的ndarray没有这两部分。本文中没有特别指定的标签,默认使用行号作为标签。
以下的代码通过iloc属性和行号获取了df5x3的第2行数据。
下面的代码为df5x3指定行标签,然后输出df5x3的值。输出内容一共有6行4列。第1列是标签。
下面的代码输出A列的数据。
不能通过df5x3[‘two’]这样的写法获取第2行数据。这样的写法只对列标题有效。
要获取第2行数据,可以采用切片的写法,如下所示。
下面的代码通过DataFrame的loc属性和行标签获取df5x3的第2行数据。
下面的代码通过loc属性、行标签切片和列标题获取了2、3、4行的后两列的数据。“’two’:’four’”是行标签的切片写法,结果是列表[‘two’, ‘three’, ‘four’]。
下面的代码通过iloc属性,行号切片获取了第2、3行的数据。
3. 读Excel文件
首先使用Excel软件把Excel文件另存为CSV格式的文件(文件后缀名是“.csv”)。然后调用read_csv函数读取数据。下面的代码调用read_csv函数,从“scores.csv”文件读入学生的成绩数据。这一文件与包含本文列出的代码的交互式文档(前面把它命名为“Pandas-codes”)位于同一个文件夹内。
学生成绩表一共有13名学生的成绩。每个学生记录包含学号(sid)和3次测验成绩,即字段test1、test2和test3。
最后3名学生的成绩有缺失。例如,序号为10的学生的第3车测验成绩缺失,在上表中显示为“NaN”,这是“Not a Number”的缩写,中文意思是“非数字”。后面会示范如何删除缺失数据。
下面的代码在读入学生成绩表的时候,指定学号作为标签(索引)。第二个参数“index_col=’sid’”起到指定学号(sid列)作为标签(索引)的作用。
4. 观察数据
调用DataFrame的info方法,能够反馈数据集内缺失数据的情况。下面的代码表明,学生成绩表scores有13行数据,字段test1有12个非空值,字段test2有12个非空值,字段test3有11个非空值。3个字段的数据类型都是浮点数。
调用DataFrame的describe方法,能够了解数据分布情况。下面的代码表明,学生成绩表scores中,mean行说的是:第一次测验(字段test1)的平均分是73.58(不考虑缺失数据),第二次测验(字段test2)的平均分是63.75,第三次测验(字段test3)的平均分是62.36。min行给出各次测验的最低分,max行给出各次测验的最高分。25%行给出的是各次测验的25%分位点的分数线。对于第一次测验(字段test1),这个分位点是72,这意味着有25%的学生的分数小于等于72分。它的50%分位点是74.5,意味着有50%的学生分数不超过74.5分。
5. 删除缺失数据
要删除有缺失数据的行,调用DataFrame的dropna方法即可。下面的代码删除了分数不全的3名学生的数据,并用scores_ok来记住没有缺失数据的成绩表。dropna方法的参数“how=’any’”意思是说,只要一行内有字段为空值,就删掉该行。如果参数为“how=’all’”,那么意思是说一行的所有字段都为空值,才删掉该行。
通过筛选若干列,能够达成删除某些列的效果。下面的代码,删除了第3列(即第3个字段),用scores_1_2记住删除该列后的结果。
6. 统计
DataFrame提供大量的统计函数。举几个例子,大家就能明白DataFrame的便捷性。
下面的代码是求每次测验的、全部学生的平均分。
下面的代码是求每次测验的最高分。
下面的代码是求每个学生的平均分。
下面的代码是求每个学生的总分。
7. 筛选和排序
下面的代码筛选出第一次测验(字段test1)的成绩不低于60分的学生。比较运算表达式的写法是“scores_ok[‘test1’]>=60”。
下面的代码筛选出第一次和第二次测验的成绩不低于60分的学生。描述筛选条件的表达式写作“(scores_ok[‘test1’]>=60) & (scores_ok[‘test2’]>=60)”。中间的符号&是“而且”的意思,两边的条件都为真,结果才为真。符号|是“或者”的意思,两边的条件有一个为真,结果就为真。上述写法中,两个圆括号不能省略,否则发生语法错误。
下面的代码对scores_ok这个DataFrame按行标签从大到小地排序。排序结果存为scores_rev变量。sort_index方法是对行标签进行排序。sort_values方法是对元素值进行排序。sort_index方法的参数“ascending=False”是指从大到小(降序)排序。使用参数“ascending=True”,则是从小到大(升序)排序。
下面的代码是按第一次测验成绩(字段test1)从小到大排序。参数“by=’test1”指明决定顺序的字段。
8. 分组统计
下面的代码把3次测验都及格的学生筛选出来。
下面的代码把有一次测验不及格的学生筛选出来。
Pandas提供groupby方法对数据进行分组汇总。下面的代码统计得出第一次测验(字段test1)的及格人数和不及格人数。
上述两行代码中,第1行代码的代码的作用是在scores_ok这个DataFrame中增加1列,列标题为’test1 passed’,这一列的各个元素值如下所示。第2行代码调用groupby方法进行分组汇总。groupby方法的参数“[‘test1 passed’]”指明实施分组的字段是’test1 passed’字段。该字段有两种值,True或False。这样就会分成两组,每种值一组。对于每一个分组,“[‘test1’]”将筛选test1字段,而后执行count方法,得出分组内元素的总数。上面的输出结果表明,没有通过的(值为False)的人数是1,通过的人数是9。
调用drop方法能够删除表中某一列。下面的代码删除了上一代码增加的’test1 passed’列。调用drop方法删除一列要有两个参数,第一个是要删除的列的名字,第二个是“axis=1”,指出删除列,而不是默认的删除行。
下面的代码增加了名为“passed”的一列。如果一个学生的3次测验都及格,passed字段的值为True,否则为False。
下面的代码统计了3次测验都及格的人数和有不及格的人数。