13.1 pandas与模型代码的接口

模型开发的通常工作流是使用pandas进行数据加载和清洗,然后切换到建模库进行建模。开发模型的重要一环是机器学习中的“特征工程”。它可以描述从原始数据集中提取信息的任何数据转换或分析,这些数据集可能在建模中有用。本书中学习的数据聚合和GroupBy工具常用于特征工程中。

优秀的特征工程超出了本书的范围,我会尽量直白地介绍一些用于数据操作和建模切换的方法。

pandas与其它分析库通常是靠NumPy的数组联系起来的。将DataFrame转换为NumPy数组,可以使用.values属性:

  1. In [10]: import pandas as pd
  2. In [11]: import numpy as np
  3. In [12]: data = pd.DataFrame({
  4. ....: 'x0': [1, 2, 3, 4, 5],
  5. ....: 'x1': [0.01, -0.01, 0.25, -4.1, 0.],
  6. ....: 'y': [-1.5, 0., 3.6, 1.3, -2.]})
  7. In [13]: data
  8. Out[13]:
  9. x0 x1 y
  10. 0 1 0.01 -1.5
  11. 1 2 -0.01 0.0
  12. 2 3 0.25 3.6
  13. 3 4 -4.10 1.3
  14. 4 5 0.00 -2.0
  15. In [14]: data.columns
  16. Out[14]: Index(['x0', 'x1', 'y'], dtype='object')
  17. In [15]: data.values
  18. Out[15]:
  19. array([[ 1. , 0.01, -1.5 ],
  20. [ 2. , -0.01, 0. ],
  21. [ 3. , 0.25, 3.6 ],
  22. [ 4. , -4.1 , 1.3 ],
  23. [ 5. , 0. , -2. ]])

要转换回DataFrame,可以传递一个二维ndarray,可带有列名:

  1. In [16]: df2 = pd.DataFrame(data.values, columns=['one', 'two', 'three'])
  2. In [17]: df2
  3. Out[17]:
  4. one two three
  5. 0 1.0 0.01 -1.5
  6. 1 2.0 -0.01 0.0
  7. 2 3.0 0.25 3.6
  8. 3 4.0 -4.10 1.3
  9. 4 5.0 0.00 -2.0

笔记:最好当数据是均匀的时候使用.values属性。例如,全是数值类型。如果数据是不均匀的,结果会是Python对象的ndarray:

  1. In [18]: df3 = data.copy()
  2. In [19]: df3['strings'] = ['a', 'b', 'c', 'd', 'e']
  3. In [20]: df3
  4. Out[20]:
  5. x0 x1 y strings
  6. 0 1 0.01 -1.5 a
  7. 1 2 -0.01 0.0 b
  8. 2 3 0.25 3.6 c
  9. 3 4 -4.10 1.3 d
  10. 4 5 0.00 -2.0 e
  11. In [21]: df3.values
  12. Out[21]:
  13. array([[1, 0.01, -1.5, 'a'],
  14. [2, -0.01, 0.0, 'b'],
  15. [3, 0.25, 3.6, 'c'],
  16. [4, -4.1, 1.3, 'd'],
  17. [5, 0.0, -2.0, 'e']], dtype=object)

对于一些模型,你可能只想使用列的子集。我建议你使用loc,用values作索引:

  1. In [22]: model_cols = ['x0', 'x1']
  2. In [23]: data.loc[:, model_cols].values
  3. Out[23]:
  4. array([[ 1. , 0.01],
  5. [ 2. , -0.01],
  6. [ 3. , 0.25],
  7. [ 4. , -4.1 ],
  8. [ 5. , 0. ]])

一些库原生支持pandas,会自动完成工作:从DataFrame转换到NumPy,将模型的参数名添加到输出表的列或Series。其它情况,你可以手工进行“元数据管理”。

在第12章,我们学习了pandas的Categorical类型和pandas.get_dummies函数。假设数据集中有一个非数值列:

  1. In [24]: data['category'] = pd.Categorical(['a', 'b', 'a', 'a', 'b'],
  2. ....: categories=['a', 'b'])
  3. In [25]: data
  4. Out[25]:
  5. x0 x1 y category
  6. 0 1 0.01 -1.5 a
  7. 1 2 -0.01 0.0 b
  8. 2 3 0.25 3.6 a
  9. 3 4 -4.10 1.3 a
  10. 4 5 0.00 -2.0 b

如果我们想替换category列为虚变量,我们可以创建虚变量,删除category列,然后添加到结果:

  1. In [26]: dummies = pd.get_dummies(data.category, prefix='category')
  2. In [27]: data_with_dummies = data.drop('category', axis=1).join(dummies)
  3. In [28]: data_with_dummies
  4. Out[28]:
  5. x0 x1 y category_a category_b
  6. 0 1 0.01 -1.5 1 0
  7. 1 2 -0.01 0.0 0 1
  8. 2 3 0.25 3.6 1 0
  9. 3 4 -4.10 1.3 1 0
  10. 4 5 0.00 -2.0 0 1

用虚变量拟合某些统计模型会有一些细微差别。当你不只有数字列时,使用Patsy(下一节的主题)可能更简单,更不容易出错。