Python机器学习库笔记(3)——pandas

Pandas全称”Python Data Analysis Library”,是python的数据分析库。

本文仅列举在各类机器学习项目中常用的一些功能。更多功能详见官方文档

本文参考了官方文档的《10分钟速成pandas》

1
2
3
4
5
# 调包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

数据类型

Pandas提供两种数据类型:Series和DataFrame。

Series是带索引的一维数据结构,如果未指定索引,则以数字自动生成。

1
2
# 创建一个Series
s = pd.Series([1,3,5,np.nan,6,8])

DataFrame是二维数据结构,数据以行和列构成,每一行和每一列都是Series对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建一个DataFrame
df = pd.DataFrame(np.random.randn(6,4), columns=['A', 'B', 'C', 'D'])

# 可从字典对象创建DataFrame
dates = pd.date_range('20180101', periods=6)
df = pd.DataFrame({
'A' : pd.date_range('20180101', periods=6),
'B' : np.random.randn(6),
'C' : s.values,
'D' : np.array([3] * 6, dtype='int32'),
'E' : pd.Categorical(["train", "train", "test", "train", "test", "train"]),
'F' : 'foo'
})

查看数据

描述性统计

Pandas的一大功能是对数据进行探索性数据分析(Exploratory Data Analysis)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看数据表维度
df.shape
# 查看前5行数据
df.head(5)
# 查看末尾5行数据
df.tail(5)
# 查看行标签
df.index
# 查看列标签
df.columns
# 查看数据表的值
df.values
# 查看每列的数据类型
df.dtypes

索引

索引是由行标签构成的列,一张表可以有不止一个索引列。未指定索引列时,默认使用从0开始的行号作为索引。

1
2
3
4
5
6
# 查看索引列
df.index
# 设置索引列
df.set_index('A')
# 重置索引列
df.reset_index(drop=True)

统计量

诸如求和(sum)等方法只对数值型的列有效,而求众数(mode)等方法对字符型的列也有效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 查看主要统计信息
df.describe()
# 求和,默认axis=0按列求和
df.sum()
# 非缺失值计数
df.count()
# 均值
df.mean()
# 标准差
df.std()
# 中位数
df.median()
# 众数
df.mode()
# 偏度
df.skew()
# 峰度
df.kurt()

协方差、相关系数

DataFrame对象调用这两个方法会对全部数值型的列相互进行计算。Series对象调用这两个方法需要指定另一个Series对象。

1
2
3
4
5
6
7
8
9
# DataFrame协方差矩阵
df.cov()
# DataFrame相关系数矩阵
df.corr()

# Series协方差
df['B'].cov(df['C'])
# Series相关系数
df['B'].corr(df['C'])

排序

DataFrame有两种排序方法:sort_values按照值排序,sort_index按照索引号排序。

1
2
3
4
# 按索引标签排序,默认axis=0为对行排序,ascending=True为升序
df.sort_index(axis=1, ascending=False)
# 按指定列的值排序
df.sort_values(by=['B'])

选择

选中

直接索引:使用类似字典的索引方法得到的是列,使用切片得到的是行。

1
2
3
4
5
6
7
# 选中一列(2种方法)
df['A']
df.A #不推荐
# 选中多列
df[['A', 'B']]
# 切片选中多行
df[1:3] #不包括冒号后的那一行

此外还有lociloc两种方法用于选中操作,loc是基于索引标签的,而iloc基于位置(即行号)的。

loc:传入的第一个参数是索引列的标签。当索引是默认的行号时,要注意和iloc的区别。此方法切片时,注意冒号左右两边的行都会被选取到。

1
2
3
4
5
6
7
8
9
# 选择一行
df.loc[1] #注意:这里的整型数字并非行号,而是代表索引标签
# 切片选择指定的行和列
df.loc[1:3, 'B':'E'] #包括冒号后的那一行
# 选择不连续的多行和多列
df.loc[[1, 3], ['B','D']] #包括冒号后的那一行
# 获取特定位置的值(2种方法)
df.loc[1, 'B']
df.at[1, 'B']

iloc:传入的第一个参数是索引所在的位置,即行号。

1
2
3
4
5
6
7
8
9
# 选择第n行
df.iloc[3]
# 切片选择
df.iloc[3:5, :2]
# 选中指定位置
df.iloc[[1,2,4],[0,2]]
# 获取特定位置的值(2种方法)
df.iloc[1,1]
df.iat[1,1]

条件筛选

可以用逻辑运算符连接多个条件表达式以进行复合筛选。

1
2
3
4
5
6
7
8
# 筛选
df[df.B > 0]
# 复合筛选
df[(df.B > 0) & (df.E=='test') ]
# 用isin筛选某列中包含指定元素的条目
df[df['E'].isin(['train'])]
# 筛选并选中指定的列
df.loc[df.B > 0, ['C']]

分组

对数据表进行分组,可以直观显示所需的部分数据、对部分数据运用函数或者利用所需数据构建新的数据表。可以利用groupby方法实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
df4 = pd.DataFrame({
'A' : ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C' : np.random.randn(8),
'D' : np.random.randn(8)
})

# 按一列分组并求和
df4.groupby('A').sum()

# 按多列分组并求和
df4.groupby(['A', 'B']).sum()

增删改

选中元素之后可以进行诸如赋值、改变数据类型等操作。

注意:涉及到对数据进行更改的方法,都会有inplace这个参数,默认值为False,不对原对象修改,创建副本并返回修改后的新值,设置为True时则不创建新的对象,直接对原始对象进行修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 数据表转置
df.T
# 查看数据类型
df['C'].dtype
# 更改数据类型
df['C'].astype('str')
# 查看唯一值
df['C'].unique()
# 查看空值
df['C'].isnull()
# 更改列名
df['C'].rename('newC')
# 对该列去重(保留第一次出现的值)
df['C'].drop_duplicates()
# 全部替换
df['C'].replace(8., 9.)
# 统计各唯一值出现的次数
df['E'].value_counts()
# 字符串操作,以大小写为例
df['E'].str.upper()
# 将所有值应用同一个函数
df['B'].apply(lambda x:x**2)

合并数据表

Pandas提供了concatappendmerge三种方法进行数据表合并。

concat:一种基本的数据表合并方式,支持横向和纵向合并。它主要接收以下参数:

  • axis:合并的方向,默认为0表示纵向合并。
  • ignore_index:是否重置索引,默认为False,这时保留原数据表的索引,设置为True则重置为新的索引。
  • join:默认为outer,表示取并集,若设置为inner则取交集。
  • join_axes:指定合并后采用的索引。
1
2
3
4
5
df1 = df = pd.DataFrame(np.random.randn(2, 4), columns=['a','b','c','d'])
df2 = df = pd.DataFrame(np.random.randn(3, 4), columns=['a','b','c','d'])
df3 = df = pd.DataFrame(np.random.randn(2, 3), columns=['a','b','c'])

pd.concat([df1, df2, df3], join='inner', ignore_index=True)

append:用法类似于concat,但只能纵向合并。

1
df1.append(df3, ignore_index=True)

merge:与concat的主要区别在于用on参数指定要连接的键。

  • on:指定要连接的一个或多个键,这个键在两张表中是一致的。
  • how:连接的方法,可选inner(取交集,默认)、outer(取并集)、left(以左表为主)、right(以右表为主)。
1
2
3
4
left = pd.DataFrame({'key': ['foo', 'bar'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'bar'], 'rval': [4, 5]})

pd.merge(left, right, on='key')

缺失值

Pandas中,缺失值用NaN表示,当创建DataFrame对象时,使用np.nan代表缺失值。

DataFrame对象使用isnull方法会返回一个布尔矩阵,显示每个位置是否是缺失值。可以灵活运用这一函数来定位缺失值。

1
2
3
4
5
6
7
8
9
10
11
12
df4 = pd.DataFrame([[0,1,2],[3,np.nan,np.nan],[4,np.nan,np.nan],[5,np.nan,6],[7,8,9]])

# 查看是否是缺失值
df4.isnull()
# 查看每列是否存在缺失值
df4.isnull().any()
# 只显示存在缺失值的行列,注意当一行存在n个缺失值时会重复输出该行n次
df4[df4.isnull().values==True]
# 每列缺失值的总数
df4.isnull().sum()
# 计算每列缺失值的比例,并从高到低输出
(df4.isnull().sum()/df4.isnull().count()).sort_values(ascending=False)

Pandas提供了一些基础的处理缺失值的方法。

1
2
3
4
5
6
7
8
# 直接舍去含有缺失值的行
df4.dropna(how='any')
# 用常数填充缺失值
df4.fillna(value=10.)
# 用前一个非缺失值填充缺失值,默认axis=0按列填充
df4.fillna(method='ffill', axis=1)
# 用后一个非缺失值填充缺失值
df4.fillna(method='bfill')

绘图

Series和DataFrame对象都具有快速绘图的功能。它们用法与matplotlib类似,可以参考我的另一篇文章:《Python机器学习库笔记(2)——matplotlib.pyplot》,本文不再赘述。

1
2
3
4
5
6
7
8
9
10
11
#Series
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2016', periods=1000))
ts = ts.cumsum()
ts.plot()

#DataFrame
df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=['A', 'B', 'C', 'D'])
df = df.cumsum()
plt.figure()
df.plot()
plt.legend(loc='best')

文件读写

Pandas支持读取csv、hdf5以及xlsx等类型的文件。

1
2
3
4
5
6
7
8
9
10
11
12
# 读取csv格式的文件
pd.read_csv('input.csv')
# 将DataFrame写入到csv格式文件
df.to_csv('output.csv')
# 读取hdf5格式的文件
pd.read_hdf('input.h5', 'df')
# 将DataFrame写入到hdf5格式文件
df.to_hdf('output.h5', 'df')
# 读取excel文件
pd.read_excel('input.xlsx', 'Sheet1', index_col=None, na_values=['NA'])
# 将DataFrame写入到xlsx格式文件
df.to_excel('output.xlsx', sheet_name='Sheet1')