Frank the Obscure 无名的弗兰克

pandas + 机器学习


几次参加国内的机器学习竞赛时, 都使用 pandas 作为数据处理库. 很遗憾一直没有取得很好的成绩, 但是既然有了尝试, 就把一点点实际的经验记录下来.

数据 io

输入方面, pd.read_csv()pd.read_table() 是最常用的两个命令1. 常用的参数有:

  • header 是否有标签行
  • names=[column names] 指定列名称

导入的数据是 pandas.DataFrame 对象

输出时, 常用 pd.to_csv():

  • header
  • index 是否输出 index, 通常都不需要(=False).

数据整理和运算

得到数据后, 经常需要做整理和处理操作, pandas 可以很方便地处理 DataFrame 2

df.loc[row, col] 或者 df.iloc[row,col] 可以选择某些行/列 操作(i/o)

  • df.loc[:, 'column_name'] == df.column_name
training_set.loc[:,'y'] = np.log10(1.001 - training_set.key_index_x)  # 赋值建立 log 变换后的新列
df['mins'] = df['time_delta'].astype('timedelta64[m]')
df_num['time'] = df_num['time'].apply(lambda x: pd.to_datetime(x, errors='coerce'))  # 赋值回原列, 注意这里用的 apply(function) 是一个比较通用的方法

time0 = df.iloc[0,:].time
df['time_delta'] = df['time'].apply(lambda x: x - time0)
  • df.loc 还可使用限定条件:
training_set.loc[training_set.key_index_x > 0.85]  # 选择 key_index_x > 0.85 的行
  • df.iloc 限定使用序号, 性能更好
top50 = training_set.sort_values(by='y').iloc[:50,:]
least50 = training_set.sort_values(by='y').iloc[-50:,:]  # 按 y 列排序之后取首尾
training_set.iloc[[4557, 4558, 5362, 5363, 5884, 5885, 5886, 5887, 5888, 5889, 5890,5891, 5892, 5893],:]  # 使用列表查看某些行的数据

df.loc 的输出常常用于后续的输入. 如使用 series.tolist()df.as_matrix()

element-wise 操作 通常可以直接进行(如上面取对数的例子)

df.describe() 可以给出统计值(包括 count mean std min max等) 配合可视化可以很快理解数据分布

缺失值

df.dropna(), df.fillna() 提供了方便的处理缺失值的方法.

如果缺失值比例不大, 最简单的处理方法就是直接舍弃:

df.dropna(how='any')

pivot/groupby

透视表/汇总也是很重要的数据整理操作, 也常常是可视化之前的准备:

# 用index 指定行, columns 指定列, values 指定值
df.pivot(index='mins', columns='product_no', values='value').plot()

grouped = training_set.groupby([training_set.draft_param1,
                                training_set.y_bin])
grouped.count()

也可使用 grouped.mean(), 甚至同时用多个函数, 获得类似 df.describe() 的效果

grouped = training_set.groupby('draft_param1')
# grouped.aggregate(np.mean)
print(grouped.y.agg([np.count_nonzero, np.mean, np.std])) ~~~
         count_nonzero      mean       std draft_param1 0                      25.0 -1.223018  0.448874 1                     239.0 -1.518699  0.410279 2                      35.0 -1.557707  0.357107 3                    4959.0 -1.504268  0.393509 4                     530.0 -1.438326  0.325457 5                    3017.0 -1.489401  0.322244 ~~~

可视化

使用 DataFrame.plot()

training_set.plot.scatter('draft_param1', 'y')  # 散点图
training_set.hist(column=['key_index_x'],bins=100)  # 只用一行命令就可以查看一列的统计分布
draft_training.hist(column=['key_index','draft_param1','draft_param2','draft_param3'],bins=10)  # 一次查看多列数据也没问题

seaborn3 也提供了直接绘制 DataFrame 的方法, 可以绘制 violinplot, boxplot 等更复杂的图

import seaborn as sns
sns.violinplot(x="draft_param1", y="y",
               data=training_set)

传入 scikit-learn

scikit-learn 的输入是 numpy.array, 因此使用 DataFrame.as_matrix(columns=[features]) 可以选择特征列输入 scikit-learn

X = training_set.as_matrix(columns=['param1', 'param2',
        'param3', 'param4',
        'param5','param6','param7',
        'param8','param9','draft_param1',
        'draft_param2','draft_param3','draft_param4',
        'draft_param5','draft_param6','draft_param7',
        'draft_param9', 'draft_param10','draft_param11'])
y = training_set.as_matrix(columns=['y']).ravel()

from sklearn.cross_validation import KFold
kf = KFold(len(training_set), n_folds=5)

from sklearn.ensemble import RandomForestRegressor
clf = RandomForestRegressor(n_estimators=100, max_depth=10)

for k, (train, test) in enumerate(kf):
    clf.fit(X[train], y[train])
    print("[fold {}], training score {:.5f}, test score {:.5f}".
          format(k, clf.score(X[train], y[train]), clf.score(X[test], y[test])))

小结

pandas 作为 python 科学计算和数据分析生态链中的重要部分, 提供了方便的数据结构和相关处理函数, 也可轻松与 numpy, scikit-learn 等库集成为完整的 pipeline.

pandas 的文档4, 以及 10 minutes to pandas5, 比本文更加详尽. 遇到问题时, 利用google 搜索关键字 (如 pandas pivottable, pandas scatter plot) 往往比翻文档更快(通常第一个是文档, 第二个开始是 stackoverflow 的问题和答案).


References


Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Similar Posts

Comments