pandas 基础与数据分析入门
学习使用给定数据集了解 pandas 以及绘制图表。
pandas 基础与安装
尽管 Python 可以用于解析 CSV 文件,但过程仍然可能较为复杂。虽然存在 csv_reader() 等库可以帮助处理,但我们仍需手动调用多个函数。这时,pandas 就派上用场了,它是一个非常优秀的数据分析库。当我们面对复杂或大规模数据集时,pandas 能提供极大的帮助。它是基于 NumPy 和 SciPy 的扩展库,具备许多便捷功能,例如直接读取 Microsoft Excel 文件、执行类似 SQL 的数据连接操作等。本课程将介绍其中一些核心功能。
pandas 有两个主要的数据结构:
- Series
- DataFrames
Series 类似于 NumPy 数组或字典,但提供了更多额外功能。
DataFrames 是一种二维数据结构,包含行和列的信息,类似于 Excel 文件中的表格。
注意:一个 Excel 文件包含行、列以及可选的标题行,这些都可以用 DataFrame 来表示。我们将在下面的例子中使用这种结构。
如果你在 Windows 上安装了 Anaconda,通常已经包含了 pandas。在 Linux 系统上,可以运行 pip install pandas 来安装。pip 会提示你是否需要同时安装其他依赖项。
分析英格兰的肥胖情况
我们将使用英国政府 2014 年提供的数据来分析英格兰的肥胖问题。数据以 Microsoft Excel 格式提供,因此我们可以轻松打开并查看其中的不同部分。
现在开始吧。
为了提高效率,我们将 pandas 导入为 pd,numpy 导入为 np。
1import pandas as pd 2import numpy as np 3data = pd.ExcelFile("Obes-phys-acti-diet-eng-2014-tab.xls")
注意:文件名 “Obes-phys-acti-diet-eng-2014-tab.xls” 是从英国政府官方网站 UK Government’s website 下载的。
让我们打开这个 .xls 文件。pandas 的一大优势是可以直接读取 Excel 文件。大多数库仅支持 CSV 格式,而 pandas 可以列出所有工作表名称:
1['Chapter 7', '7.1', '7.2', '7.3', '7.4', '7.5', '7.6', '7.7', '7.8', '7.9', '7.10']
一个 工作表 就是 Excel 中的一张“页面”。用户通常将数据拆分到多个工作表中,而不是全部放在一个庞大且难以管理的单一工作表里。
按性别划分的肥胖情况
让我们看看数据:
No configuration found for ID: f07ded569b23fa4fc7b33b5ea0cc63c0d43315ae32491818b26084d0722be854
共有四列:
- Year(年份)
- Total(总数)
- Males(男性)
- Females(女性)
年份这一列没有标题,查看第 5 行可以发现年份标题为空。我们将介绍两种读取数据的方法。第一种方法是我们自己定义列标题。请看代码窗口中高亮的部分。
我们定义了一个包含四个列名的列表:year、total、males 和 females。
观察实际数据可知,前 4 行和后 14 行包含的是无关信息,因此我们可以跳过它们(使用 skiprows=4 和 skipfooter=14)。最后,我们告诉 pandas 使用我们定义的列表 names=columns1 作为列名。
然后使用 print(data_gender) 输出 data_gender:
1import pandas as pd 2import matplotlib.pyplot as plt 3 4def obesity(excelfile="Obes-phys-acti-diet-eng-2014-tab.xls", nogui = False): 5 data = pd.ExcelFile(excelfile) 6 7 # 读取 Excel 文件中的 7.1 部分 8 9 # 定义要读取的列 10 columns1 = ['year', 'total', 'males', 'females'] 11 12 data_gender = data.parse(u'7.1', skiprows=4, skipfooter=14, names=columns1) 13 print (data_gender) 14 15obesity()
观察索引为 0 的条目,其值为 NaN。为什么会这样?查看原始电子表格我们会发现,第 6 行有一个空格,目的是让表格更易读。由于该单元格为空,pandas 会将其识别为 Not A Number (NaN)。为解决这个问题,我们将使用内置的 dropna() 函数。通过设置 inplace=True,直接修改原 DataFrame。
请看下方代码中第 17 行的高亮部分。
再次查看输出结果:
1import pandas as pd 2import matplotlib.pyplot as plt 3 4def obesity(excelfile="Obes-phys-acti-diet-eng-2014-tab.xls", nogui = False): 5 data = pd.ExcelFile(excelfile) 6 #print(data.sheet_names) 7 8 # 读取 Excel 文件中的 7.1 部分 9 10 # 定义要读取的列 11 columns1 = ['year', 'total', 'males', 'females'] 12 13 data_gender = data.parse(u'7.1', skiprows=4, skipfooter=14, names=columns1) 14 15 # 删除缺失值 16 data_gender.dropna(inplace = True) 17 18 print (data_gender) 19 20obesity()
现在可以看到 NaN 值已消失。但这样做又带来了一个新问题:我们在开头多出了一列索引(从 1, 2, 3 开始递增),而这并不是我们需要的。我们希望将年份设为索引:
1import pandas as pd 2import matplotlib.pyplot as plt 3 4def obesity(excelfile="Obes-phys-acti-diet-eng-2014-tab.xls", nogui = False): 5 data = pd.ExcelFile(excelfile) 6 #print(data.sheet_names) 7 8 # 读取 Excel 文件中的 7.1 部分 9 10 # 定义要读取的列 11 columns1 = ['year', 'total', 'males', 'females'] 12 13 data_gender = data.parse(u'7.1', skiprows=4, skipfooter=14, names=columns1) 14 15 # 删除缺失值 16 data_gender.dropna(inplace = True) 17 18 # 将年份设为索引 19 data_gender.set_index('year', inplace=True) 20 print (data_gender) 21 22obesity()
至此,数据已整理成适合绘图的格式。
接下来,我们将上述所有代码整合起来,并绘制图表,以比较不同性别之间的肥胖率变化。
1import pandas as pd 2import matplotlib.pyplot as plt 3 4def obesity(excelfile="Obes-phys-acti-diet-eng-2014-tab.xls", nogui = False): 5 data = pd.ExcelFile(excelfile) 6 print(data.sheet_names) 7 8 # 读取 Excel 文件中的 7.1 部分 9 10 # 定义要读取的列 11 columns1 = ['year', 'total', 'males', 'females'] 12 13 data_gender = data.parse('7.1', skiprows=4, skipfooter=14, names=columns1) 14 #print data_gender 15 16 # 删除缺失值 17 data_gender.dropna(inplace = True) 18 #print data_gender 19 20 data_gender.set_index('year', inplace=True) 21 22 # 绘制所有数据 23 data_gender.plot() 24 25 26 if not nogui: 27 plt.show() 28 plt.savefig('output/plot.png') 29 30 31 32 33if __name__ == "__main__": 34 obesity()
可以看出,在相同时间段内,女性的肥胖率上升幅度明显高于男性。