人工智能之Python数据挖掘—— pandas 库
一. pandas:Python 数据分析库
pandas 是一个专门用于数据分析的开源 Python 库。使用 Python 语言研究和分析数据集,做相关统计分析和决策时,pandas 都是基础工具。
数据分析工作需要一个专门的库,,它能够以最简单的方式提供数据处理。数据抽取和数据操作所需的全部工具。开发 pandas 正是为了满足这个需求。
以 NumPy 库作为 Python 库 pandas 的基础进行设计,不仅使 pandas 能和其他大多数模块相兼容,而且还能借力 NumPy 模块在计算方面性能高的优势。此外,pandas 没有使用 Python 已有的内置数据结构,也没有使用其他库的数据结构,而是开发了两种新型的数据结构,用它们去更方便地管理与 SQL 关系数据库和 Excel 工作表具有类似特征的数据。
1. pandas 数据结构简介
pandas 的核心为两个数据结构,数据分析相关的所有事务都是围绕着这两种结构进行的:
- Series
- DataFrame
Series 这类数据结构用于存储一个序列这样的一维数据,而 DataFrame 作为更复杂的数据结构,则用于存储多维数据。
1.1 Series 对象
pandas 库的 Series 对象用来表示一维数据结构,跟数组类似,但多了一些额外的功能。它的内部结构由两个相互关联的数组组成,其中主数组用来存放数据(NumPy 任意类型数据)。主数组的每个元素都有一个与之相关联的标签,这些标签存储在另外一个叫做 Index 的数组中。
| Series | |
| index | value |
| 0 | 12 |
| 1 | -4 |
| 2 | 7 |
| 3 | 9 |
1.1.1 声明 Series 对象
调用 Series()构造函数,把要存放在 Series 对象中的数据以数组形式传入,就能创建一个如上图所示的 Series 对象。
>>> s=pd.Series([12,-4,7,9]) >>> s 0 12 1 -4 2 7 3 9
dtype: int64
从 Series 的输出可以看到,左侧 Index 是一列标签,右侧是标签对应的元素。
声明 Series 时,若不指定标签,pandas 默认使用从 0 开始依次递增的数值作为标签。这种情况下,标签与 Series 对象中元素的索引(在数组中的位置)一致。
然而,最好使用有意义的标签,用以区分和识别每个元素,而不用考虑元素插入到 Series 中的顺序。
因此,调用构造函数时,就需要指定 index 选项,把存放有标签的数组赋给它,其中标签为字符串类型。
>>> s=pd.Series([12,-4,7,9]),index=[\'a\',\'b\',\'c\',\'d\'] >>> s a 12 b -4 c 7 d 9
dtype:int64
如果想分别查看组成 Series 对象的两个数组,可以像下面这样调用它的两个属性:index(索引)和 values(元素)。
>>> s.values array([12,-4,7,9],dtype=64) >>> s.index Index([u\'a\',u\'b\',u\'c\',u\'d\'],dtype=\'object\') 不懂
1.1.2 选择内部元素
若想获取 Series 对象内部的元素,把它作为普通的 NumPy 数组,指定键即可。
>>> s[2]
7
或者,指定位于索引位置处的标签。
>>> s[\'b\']
-4
跟从 NumPy 数组选择多个元素的方法相同,可像下面这样选取多项:
>>> s[0:2]
a 12
b -4
dtype:int64
或者, 这种情况甚至可以使用元素对应的标签,只不过要把标签放到数组中:
>>> s[\'b\',\'c\']
b -4
c 7
dtype:int64
1.1.3 为元素赋值
赋值方法可以用索引或标签选取元素后进行赋值。
>>> s[1]=0 >>> s a 12 b 0 c 7 d 9 dtype: int64 >>> s[\'b\']=1 >>> s a 12 b 1 c 7 d 9 dtype: int64
1.1.4 用 NumPy 数组或其他 Series 对象定义新 Series 对象
>>> arr=np.array([1,2,3,4]) >>> s3=pd.Series(arr) >>> s3 0 1 1 2 2 3 3 4 dtype: int32 >>> s4=pd.Series(s) >>> s4 a 12 b 1 # 教材上是 4 ??? c 7 d 9 dtype: int64
然而,新 Series 对象中的元素不是原 Numpy 数组或 Series 对象元素的副本,而是对它们的引用。也就是说,这些对象是动态插入到新 Series 对象中,如果改变原有对象元素的值,新 Series 对象中这些元素也会相应发生变化。
>>> s3 0 1 1 2 2 3 3 4 dtype: int32 >>> arr[2]=-2 >>> s3 0 1 1 2 2 -2 3 4 dtype: int32
上述例子,改动 arr 数组第三个元素的值,同时也会修改 Series 对象 s3 中相应的元素。
1.1.5 筛选元素
pandas 库的开发是以 NumPy 库为基础的,因此就数据结构而言,NumPy 数组的多种操作方法得以扩展到 Series 对象中,其中就有根据条件筛选数据结构中的元素这一方法。
例如要获取 Series 对象中所有大于8的元素,可使用以下代码:
>>> s[s>8] a 12 d 9 dtype: int64
1.1.6 Series 对象运算和数学函数
适用于 NumPy 数组的运算(+、-、*、/)或其他数学函数,也适用于 Series 对象。
至于运算符,直接用来编写算术表达式即可
>>> s / 2 a 6.0 b -2.0 # ???? c 3.5 d 4.5 dtype: float64
然而,至于 NumPy 库的数学函数,必须指定它们的出处 np,并把 Series 实例作为参数传入。
>>> np.log(s) a 2.484907 b NaN c 1.945910 d 2.197225 dtype: float 64
1.1.7 Series 对象的组成元素
Series 对象往往包含重复的元素,如果想知道里面都包含哪些元素,统计元素重复出现的次数或判断一个元素是否在 Series 中。
首先声明一个包含多个重复元素的 Series 对象。
>>> serd=pd.Series([1,0,2,1,2,3],index=[\'white\',\'white\',\'blue\',\'green\',\'green\',\'yellow\']) >>> serd white 1 white 0 blue 2 green 1 green 2 yellow 3 dtype: int64
要想知道 Series 对象包含多少个不同的元素,可使用 unique()函数。其返回结果为一个数组,包含 Series 去重后的元素,但顺序看上去很随意。
>>> serd.nuique()
array([1,0,2,3],dtype=int64)
跟 unique()函数相似的另外一个函数是 value_counts()函数,它不仅返回各个不同的元素,还计算每个元素在 Series 中的出现次数。
>>> serd.value_counts() 2 2 1 2 3 1 0 1 dtype: int64
最后,isin()函数用来判断所属关系,也就是判断给定的一列元素是否包含在数据结构之中。isin()函数返回布尔值,可用于筛选 Series 或 DataFrame列中的数据。
>>> serd.isin([0,3]) # 选取serd中值为0或3的行
white False
white True
blue False
green False
green False
yellow True
dtype: bool
>>> serd[serd.isin([0,3])]
white 0
yellow 3
dtype: int64
1.1.8 NaN
在前面的一个例子中,求负数的对数,得到的返回结果为 NaN(Not a Number,非数值)。数据结构中若字段为空或者不符合数字的定义时,用这个特定的值来表示。
一般来讲,NaN 值表示数据有问题,必须对其进行处理,尤其是在数据分析时。从某些数据源抽取数据时遇到了问题,甚至是数据源缺失数据,往往就会产生这类数据。进一步来讲,计算负数的对数,执行计算或函数时抛出异常等特定情况,也可能产生这类数据。
尽管 NaN 值是数据有问题才产生的,然而在 panads 中是可以定义这种类型的数据,并把它添加到 Series 等数据结构中的。创建数据结构时,可为数组中元素缺失的项输入 np.NaN。
>>> s2=pd.Series([5,-3,np.NaN,14]) >>> s2 0 5 1 -3 2 NaN 3 14
isnull()和notnull()函数用来识别没有对应元素的索引时非常好用。
>>> s2.isull() 0 False 1 False 2 True 3 False dtype: bool >>> s2.notnull() 0 True 1 True 2 False 3 True
dtype: bool
上述两个函数返回两个由布尔值组成的 Series 对象,其元素值是 True 还是 False 取决于原 Series 对象的元素是否为 NaN。如果是 NaN,isnull()函数返回值为 True;反之,如果不是 NaN,notnull()函数返回值为 True。这两个函数可用作筛选条件。
>>> s2[s2.notnull()] 0 5 1 -3 3 14 dtype: float64 >>> s2[s2.isnull()] 2 NaN dtype: float64
1.1.9 Series 用作字典
还可以把 Series 对象当做字典对象来用。定义 Series 对象时,就可以利用这种相似性。事实上,可以用事先定义好的字典来创建 Series 对象。
>>> mydict={\'red\':2000,\'blue\':1000,\'yellow\':500,\'orange\':1000}
>>> myseries=pd.Series(mydict)
blue 1000
orange 1000
red 2000
yellow 500
dtype: int64
上述例子中,索引数组用字典的键来填充,每个索引所对应的元素为用作索引的键在字典中对应的值。可以单独指定索引,pandas 会控制字典的键和数组索引标签之间的相关性。如遇缺失值处,pandas 就会为其添加 NaN。
>>> colors=[\'red\',\'yellow\',\'orange\',\'blue\',\'green\'] >>> myseries=pd.Series(mydict,index=colors) red 2000 yellow 500 orange 1000 blue 1000 green NaN dtype: float64
1.1.10 Series 对象之间的运算
之前有 Series 对象和标量之间的数学运算,Series 对象之间也可以进行这类运算,甚至标签也可以参与运算。事实上,Series 这种数据结构在运算时有一大优点,它能够通过识别标签对齐不一致的数据。
在下面的例子中,我们来求只有部分元素标签相同的两个 Series 对象之和。
>>> mydict2={\'red\':400,\'yellow\':1000,\'black\':700}
>>> myseries2=pd.Series(mydict2)
>>> myseries+myseries2
black NaN
blue NaN
orange NaN
green NaN
red 2400
yellow 1500
dtype: float64
上述运算得到一个新 Series 对象,其中只对标签相同的元素求和。其他只属于任何一个 Series 对象的标签也被添加到新对象中,只不过它们的值均为 NaN。
1.2 DataFrame 对象
DataFrame 这种列表式数据结构跟工作表(最常见的是 Excel 工作表)极为相似,其设计初衷是将 Series 的使用场景由一维扩展到多维。DataFrame 由一定顺序排列的多列数据组成,各列的数据类型可以有所不同(数值、字符串或布尔值等),如下图所示
| DataFrame | |||
| columns | |||
| index | color | object | price |
| 0 | blue | ball | 1.2 |
| 1 | green | pen | 1.0 |
| 2 | yellow | pencil | 0.6 |
| 3 | red | paper | 0.9 |
| 4 | white | mug | 1.7 |
Series 对象的 Index 数组存放有每个元素的标签,而 DataFrame 对象则有所不同,它有两个索引数组。第一个数组与行,它与 Series 的索引数组极为相似。每个标签与标签所在行的所有元素相关联。而第二个数组包含一系列列标签,每个标签与一列数据相关联。
DataFrame 还可以理解为一个由 Series 组成的字典,其中每一列的名称为字典的键,形成 DataFrame 的列的 Series 作为字典的值。进一步来说,每个 Series 的所有元素映射到叫做 Index 的标签数组。
1.2.1 定义 DataFrame 对象
新建 DataFrame 对象的最常用方法是传递一个 dict 对象给 DataFrame()构造函数。dict 对象以每一列的名称作为键,每个键都有一个数组作为值。
>>> data={\'color\':[\'blue\',\'green\',\'yellow\',\'red\',\'white\'],
\'object\':[\'ball\',\'pen\',\'pencil\',\'paper\',\'mug\'],
\'price\':[1.2,1.0,0.6,0.9,1.7]}
>>> frame=pd.DataFrame(data)
>>> frame
color object price
0 blue ball 1.2
1 green pen 1.0
2 yellow pencil 0.6
3 red paper 0.9
4 white mug 1.7
如果用来创建 DataFrame 对象的 dict 对象包含一些用不到的数据,可以只选择自己感兴趣的。在 DataFrame 构造函数中,用 columns 选项指定需要的列即可。新建的 DataFrame 各列顺序与指定的列顺序一致,而与它们在字典中的顺序无关。
>>> frame2