Python可以很好地完成预处理任务,本文对python常用的numpy & pandas做一些总结。
1. 文本读写
python本身就带有open()函数,配合readline()/write()函数可以完成读写功能。但注意pandas也有很强大的读写能力,包括函数
read_csv()
to_csv()
read_excel()
to_excel()。
这里提一点:read_csv()函数可以指定index,column name,encoding type,header等等。作者曾经遇到过一个比较strange的问题,read_csv()与read_excel()的不同。比如,读入的第一列是c1,c2,c3,...cn。但是read_csv()的c1前面却带了一个未知符号`,即显示成了`c1。当时调了半天都没有明白这个`是怎么产生的,不知道哪位大神能够解答。最后无奈用read_excel()才解决。
python还有一个叫codecs的模块,可以很好的解决decode与encode的问题,它可以在读入时就选择相应的coding方式。
2. 数据处理
这一部分要说的内容就太多了,先来简单区分一下numpy和pandas。简单说,pandas是基于numpy的,numpy可以定义array和dataframe,pandas中可以定义dataframe和series。(可能不是很准确)
之前提到的文本读写,pandas可以直接将内容读成dataframe或series的形式。同时dataframe和series也可以由list或dictionary生成。这里我的理解是dictionary就是带有列名的list。
dataframe有一个函数是astype(),可以修改元素类型。这里要注意一点:当dataframe或series含有null值时,astype(np.float64)或astype(np.int64)将不成功,必须将null值去除后才能convert string into numeric value。去除或者填充null值可以使用dropna()或者fillna()函数。
强大的lambda函数
lambda函数可以应用于map与apply函数中,对于调用map与apply的dataframe,可以自动对dataframe做element-wise的操作!!!
关于异常值处理,目前我还只用到了缺失值处理,但不清楚出现异常值,有没有办法将它设为0?可以考虑使用lamda函数。
df['new_col'] = df['old_col'].map( lambda x: func(x) )
map是一个非常强大的函数,这里再举一个例子,Gender原先有两个值Male和Female,这里要将其转为1和0。
df['Gender'] = df['Sex'].map( {'female': 0, 'male': 1} ).astype(int)
再举一个例子,有一个dataframe,先需要对其中某几列做操作,从而得到新的一列,可以用如下方法:
df[new_column] = df.apply(lambda x : func(x[col1],x[col2],...,x[coln])
, axis=1)
根据以上例子可以发现,lambda函数中的x可以是某一行,可以是某一列,也可以是某个dataframe。
行列添加与转置
pandas添加行列以及行列转换不是特别方便。比如为了实现合并多列数据得到一个新的DataFrame,可以使用pd.concat()将多行数据合在一起,通过指定参数axis=1即可按列合并。
但它的一大长处是支持类似sql的基本操作,这点非常强大。
pandas提供了一个类似于关系数据库的连接(join)操作的方法,可以根据一个或多个键将不同DataFrame中的行连接起来语法如下:
merge(left, right, how='inner', on=None, left_on=None, right_on=None,
left_index=False, right_index=False, sort=True,
suffixes=('_x', '_y'), copy=True, indicator=False)
用于通过一个或多个键将两个数据集的行连接起来,类似于 SQL 中的 JOIN。该函数的典型应用场景是,针对同一个主键存在两张包含不同字段的表,现在我们想把他们整合到一张表里。在此典型情况下,结果集的行数并没有增加,列数则为两个元数据的列数和减去连接键的数量。
on=None 用于显示指定列名(键名),如果该列在两个对象上的列名不同,则可以通过 left_on=None, right_on=None 来分别指定。或者想直接使用行索引作为连接键的话,就将 left_index=False, right_index=False 设为 True。
how='inner' 参数指的是当左右两个对象中存在不重合的键时,取结果的方式:inner 代表交集;outer 代表并集;left 和 right 分别为取一边。suffixes=('_x','_y') 指的是当左右对象中存在除连接键外的同名列时,结果集中的区分方式,可以各加一个小尾巴。对于多对多连接,结果采用的是行的笛卡尔积。
参数说明:
left与right:两个不同的DataFramehow:指的是合并(连接)的方式有inner(内连接),left(左外连接),right(右外连接),outer(全外连接);默认为inner on : 指的是用于连接的列索引名称。必须存在右右两个DataFrame对象中,如果没有指定且其他参数也未指定则以两个DataFrame的列名交集做为连接键left_on:左则DataFrame中用作连接键的列名;这个参数中左右列名不相同,但代表的含义相同时非常有用。
right_on:右则DataFrame中用作 连接键的列名left_index:使用左则DataFrame中的行索引做为连接键right_index:使用右则DataFrame中的行索引做为连接键sort:默认为True,将合并的数据进行排序。在大多数情况下设置为False可以提高性能
suffixes:字符串值组成的元组,用于指定当左右DataFrame存在相同列名时在列名后面附加的后缀名称,默认为('_x','_y')copy:默认为True,总是将数据复制到数据结构中;大多数情况下设置为False可以提高性能indicator:在 0.17.0中还增加了一个显示合并数据中来源情况;如只来自己于左边(left_only)、两者(both)
3. 学习模型
python有非常强大的sklearn工作包,已经成为最常用的ml工具之一。在sklearn包中,数据要求为数组,而不是pandas的dataframe。
因此经过前面的数据处理,仍然有两件事需要完成:
决定我们需要留下那些列
将pandas.DataFrame转化回numpy.array。
在pandas中你可以用.info()方法查看列的类型,或者直接输入df.dtypes。
若要仅显示type为object的列:
df.dtypes[df.dtypes.map(lambda x: x=='object')]
下一步是用drop()去掉我们不用的这些列,用dropna()去除含有缺失值的行,最终的步骤是将其转化回Numpy数组:
train_data = df.values
最后来个进阶点的问题:
现在我有一个样本集df,我想将其随机打乱后抽取其中的N个作为训练集剩下的作为测试集,该怎么做呢?