Python 数据分析(PYDA)第三版(六)(1)

简介: Python 数据分析(PYDA)第三版(六)

十二、Python 建模库介绍

原文:wesmckinney.com/book/modeling

译者:飞龙

协议:CC BY-NC-SA 4.0

此开放访问网络版本的《Python 数据分析第三版》现已作为印刷版和数字版的伴侣提供。如果您发现任何勘误,请在此处报告。请注意,由 Quarto 生成的本站点的某些方面与 O’Reilly 的印刷版和电子书版本的格式不同。

如果您发现本书的在线版本有用,请考虑订购纸质版无 DRM 的电子书以支持作者。本网站的内容不得复制或再生产。代码示例采用 MIT 许可,可在 GitHub 或 Gitee 上找到。

在本书中,我专注于为在 Python 中进行数据分析提供编程基础。由于数据分析师和科学家经常报告花费大量时间进行数据整理和准备,因此本书的结构反映了掌握这些技术的重要性。

您用于开发模型的库将取决于应用程序。许多统计问题可以通过简单的技术解决,如普通最小二乘回归,而其他问题可能需要更高级的机器学习方法。幸运的是,Python 已经成为实现分析方法的首选语言之一,因此在完成本书后,您可以探索许多工具。

在本章中,我将回顾一些 pandas 的特性,这些特性在您在 pandas 中进行数据整理和模型拟合和评分之间来回切换时可能会有所帮助。然后,我将简要介绍两个流行的建模工具包,statsmodelsscikit-learn。由于这两个项目都足够庞大,值得有自己的专门书籍,因此我没有尝试全面介绍,而是建议您查阅这两个项目的在线文档,以及一些其他基于 Python 的数据科学、统计学和机器学习书籍。

12.1 pandas 与模型代码之间的接口

模型开发的常见工作流程是使用 pandas 进行数据加载和清理,然后切换到建模库来构建模型本身。模型开发过程中的一个重要部分被称为特征工程,在机器学习中。这可以描述从原始数据集中提取信息的任何数据转换或分析,这些信息在建模环境中可能有用。我们在本书中探讨的数据聚合和 GroupBy 工具经常在特征工程环境中使用。

虽然“好”的特征工程的细节超出了本书的范围,但我将展示一些方法,使在 pandas 中进行数据操作和建模之间的切换尽可能轻松。

pandas 与其他分析库之间的接触点通常是 NumPy 数组。要将 DataFrame 转换为 NumPy 数组,请使用to_numpy方法:

In [12]: data = pd.DataFrame({
 ....:     'x0': [1, 2, 3, 4, 5],
 ....:     'x1': [0.01, -0.01, 0.25, -4.1, 0.],
 ....:     'y': [-1.5, 0., 3.6, 1.3, -2.]})
In [13]: data
Out[13]: 
 x0    x1    y
0   1  0.01 -1.5
1   2 -0.01  0.0
2   3  0.25  3.6
3   4 -4.10  1.3
4   5  0.00 -2.0
In [14]: data.columns
Out[14]: Index(['x0', 'x1', 'y'], dtype='object')
In [15]: data.to_numpy()
Out[15]: 
array([[ 1.  ,  0.01, -1.5 ],
 [ 2.  , -0.01,  0.  ],
 [ 3.  ,  0.25,  3.6 ],
 [ 4.  , -4.1 ,  1.3 ],
 [ 5.  ,  0.  , -2.  ]])

回到 DataFrame,正如您可能从前几章中记得的那样,您可以传递一个二维的 ndarray,其中包含可选的列名:

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

to_numpy方法旨在在数据是同质的情况下使用,例如所有的数值类型。如果您有异构数据,结果将是一个 Python 对象的 ndarray:

In [18]: df3 = data.copy()
In [19]: df3['strings'] = ['a', 'b', 'c', 'd', 'e']
In [20]: df3
Out[20]: 
 x0    x1    y strings
0   1  0.01 -1.5       a
1   2 -0.01  0.0       b
2   3  0.25  3.6       c
3   4 -4.10  1.3       d
4   5  0.00 -2.0       e
In [21]: df3.to_numpy()
Out[21]: 
array([[1, 0.01, -1.5, 'a'],
 [2, -0.01, 0.0, 'b'],
 [3, 0.25, 3.6, 'c'],
 [4, -4.1, 1.3, 'd'],
 [5, 0.0, -2.0, 'e']], dtype=object)

对于某些模型,您可能希望仅使用部分列。我建议使用loc索引和to_numpy

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

一些库原生支持 pandas,并自动完成一些工作:从 DataFrame 转换为 NumPy,并将模型参数名称附加到输出表或 Series 的列上。在其他情况下,您将不得不手动执行这种“元数据管理”。

在 Ch 7.5:分类数据中,我们看过 pandas 的Categorical类型和pandas.get_dummies函数。假设我们的示例数据集中有一个非数字列:

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

如果我们想用虚拟变量替换'category'列,我们创建虚拟变量,删除'category'列,然后将结果连接:

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

使用虚拟变量拟合某些统计模型时存在一些微妙之处。当您拥有不仅仅是简单数字列时,使用 Patsy(下一节的主题)可能更简单且更不容易出错。

12.2 使用 Patsy 创建模型描述

Patsy是一个用于描述统计模型(尤其是线性模型)的 Python 库,它使用基于字符串的“公式语法”,受到 R 和 S 统计编程语言使用的公式语法的启发(但并非完全相同)。在安装 statsmodels 时会自动安装它:

conda install statsmodels

Patsy 在为 statsmodels 指定线性模型方面得到很好的支持,因此我将重点介绍一些主要功能,以帮助您快速上手。Patsy 的公式是一种特殊的字符串语法,看起来像:

y ~ x0 + x1

语法a + b并不意味着将a加到b,而是这些是为模型创建的设计矩阵中的patsy.dmatrices函数接受一个公式字符串以及一个数据集(可以是 DataFrame 或数组字典),并为线性模型生成设计矩阵:

In [29]: data = pd.DataFrame({
 ....:     'x0': [1, 2, 3, 4, 5],
 ....:     'x1': [0.01, -0.01, 0.25, -4.1, 0.],
 ....:     'y': [-1.5, 0., 3.6, 1.3, -2.]})
In [30]: data
Out[30]: 
 x0    x1    y
0   1  0.01 -1.5
1   2 -0.01  0.0
2   3  0.25  3.6
3   4 -4.10  1.3
4   5  0.00 -2.0
In [31]: import patsy
In [32]: y, X = patsy.dmatrices('y ~ x0 + x1', data)

现在我们有:

In [33]: y
Out[33]: 
DesignMatrix with shape (5, 1)
 y
 -1.5
 0.0
 3.6
 1.3
 -2.0
 Terms:
 'y' (column 0)
In [34]: X
Out[34]: 
DesignMatrix with shape (5, 3)
 Intercept  x0     x1
 1   1   0.01
 1   2  -0.01
 1   3   0.25
 1   4  -4.10
 1   5   0.00
 Terms:
 'Intercept' (column 0)
 'x0' (column 1)
 'x1' (column 2)

这些 Patsy DesignMatrix实例是带有附加元数据的 NumPy ndarrays:

In [35]: np.asarray(y)
Out[35]: 
array([[-1.5],
 [ 0. ],
 [ 3.6],
 [ 1.3],
 [-2. ]])
In [36]: np.asarray(X)
Out[36]: 
array([[ 1.  ,  1.  ,  0.01],
 [ 1.  ,  2.  , -0.01],
 [ 1.  ,  3.  ,  0.25],
 [ 1.  ,  4.  , -4.1 ],
 [ 1.  ,  5.  ,  0.  ]])

您可能会想知道Intercept项是从哪里来的。这是线性模型(如普通最小二乘回归)的一个约定。您可以通过在模型中添加+ 0项来抑制截距:

In [37]: patsy.dmatrices('y ~ x0 + x1 + 0', data)[1]
Out[37]: 
DesignMatrix with shape (5, 2)
 x0     x1
 1   0.01
 2  -0.01
 3   0.25
 4  -4.10
 5   0.00
 Terms:
 'x0' (column 0)
 'x1' (column 1)

Patsy 对象可以直接传递到像numpy.linalg.lstsq这样的算法中,该算法执行普通最小二乘回归:

In [38]: coef, resid, _, _ = np.linalg.lstsq(X, y, rcond=None)
• 1

模型元数据保留在design_info属性中,因此您可以重新附加模型列名称到拟合系数以获得一个 Series,例如:

In [39]: coef
Out[39]: 
array([[ 0.3129],
 [-0.0791],
 [-0.2655]])
In [40]: coef = pd.Series(coef.squeeze(), index=X.design_info.column_names)
In [41]: coef
Out[41]: 
Intercept    0.312910
x0          -0.079106
x1          -0.265464
dtype: float64

Patsy 公式中的数据转换

您可以将 Python 代码混合到您的 Patsy 公式中;在评估公式时,库将尝试在封闭范围中找到您使用的函数:

In [42]: y, X = patsy.dmatrices('y ~ x0 + np.log(np.abs(x1) + 1)', data)
In [43]: X
Out[43]: 
DesignMatrix with shape (5, 3)
 Intercept  x0  np.log(np.abs(x1) + 1)
 1   1                 0.00995
 1   2                 0.00995
 1   3                 0.22314
 1   4                 1.62924
 1   5                 0.00000
 Terms:
 'Intercept' (column 0)
 'x0' (column 1)
 'np.log(np.abs(x1) + 1)' (column 2)

一些常用的变量转换包括标准化(均值为 0,方差为 1)和中心化(减去均值)。Patsy 具有内置函数用于此目的:

In [44]: y, X = patsy.dmatrices('y ~ standardize(x0) + center(x1)', data)
In [45]: X
Out[45]: 
DesignMatrix with shape (5, 3)
 Intercept  standardize(x0)  center(x1)
 1         -1.41421        0.78
 1         -0.70711        0.76
 1          0.00000        1.02
 1          0.70711       -3.33
 1          1.41421        0.77
 Terms:
 'Intercept' (column 0)
 'standardize(x0)' (column 1)

作为建模过程的一部分,您可以在一个数据集上拟合模型,然后基于另一个数据集评估模型。这可能是一个保留部分或稍后观察到的新数据。当应用诸如中心化和标准化之类的转换时,您在使用模型基于新数据形成预测时应当小心。这些被称为有状态转换,因为在转换新数据时必须使用原始数据集的统计数据,如均值或标准差。

patsy.build_design_matrices函数可以使用原始样本内数据的保存信息对新的样本外数据应用转换:

In [46]: new_data = pd.DataFrame({
 ....:     'x0': [6, 7, 8, 9],
 ....:     'x1': [3.1, -0.5, 0, 2.3],
 ....:     'y': [1, 2, 3, 4]})
In [47]: new_X = patsy.build_design_matrices([X.design_info], new_data)
In [48]: new_X
Out[48]: 
[DesignMatrix with shape (4, 3)
 Intercept  standardize(x0)  center(x1)
 1          2.12132        3.87
 1          2.82843        0.27
 1          3.53553        0.77
 1          4.24264        3.07
 Terms:
 'Intercept' (column 0)
 'standardize(x0)' (column 1)
 'center(x1)' (column 2)]

因为 Patsy 公式中加号(+)并不表示加法,所以当您想按名称从数据集中添加列时,您必须将它们包装在特殊的I函数中:

In [49]: y, X = patsy.dmatrices('y ~ I(x0 + x1)', data)
In [50]: X
Out[50]: 
DesignMatrix with shape (5, 2)
 Intercept  I(x0 + x1)
 1        1.01
 1        1.99
 1        3.25
 1       -0.10
 1        5.00
 Terms:
 'Intercept' (column 0)
 'I(x0 + x1)' (column 1)

Patsy 在patsy.builtins模块中还有几个内置转换。请查看在线文档以获取更多信息。

分类数据有一类特殊的转换,接下来我会解释。

分类数据和 Patsy

非数字数据可以以多种不同的方式转换为模型设计矩阵。本书不涉及这个主题的完整处理,最好是在统计课程中学习。

当您在 Patsy 公式中使用非数字术语时,默认情况下它们会被转换为虚拟变量。如果有一个截距,将会有一个级别被排除以避免共线性:

In [51]: data = pd.DataFrame({
 ....:     'key1': ['a', 'a', 'b', 'b', 'a', 'b', 'a', 'b'],
 ....:     'key2': [0, 1, 0, 1, 0, 1, 0, 0],
 ....:     'v1': [1, 2, 3, 4, 5, 6, 7, 8],
 ....:     'v2': [-1, 0, 2.5, -0.5, 4.0, -1.2, 0.2, -1.7]
 ....: })
In [52]: y, X = patsy.dmatrices('v2 ~ key1', data)
In [53]: X
Out[53]: 
DesignMatrix with shape (8, 2)
 Intercept  key1[T.b]
 1          0
 1          0
 1          1
 1          1
 1          0
 1          1
 1          0
 1          1
 Terms:
 'Intercept' (column 0)
 'key1' (column 1)

如果从模型中省略截距,那么每个类别值的列将包含在模型设计矩阵中:

In [54]: y, X = patsy.dmatrices('v2 ~ key1 + 0', data)
In [55]: X
Out[55]: 
DesignMatrix with shape (8, 2)
 key1[a]  key1[b]
 1        0
 1        0
 0        1
 0        1
 1        0
 0        1
 1        0
 0        1
 Terms:
 'key1' (columns 0:2)

数值列可以使用C函数解释为分类列:

In [56]: y, X = patsy.dmatrices('v2 ~ C(key2)', data)
In [57]: X
Out[57]: 
DesignMatrix with shape (8, 2)
 Intercept  C(key2)[T.1]
 1             0
 1             1
 1             0
 1             1
 1             0
 1             1
 1             0
 1             0
 Terms:
 'Intercept' (column 0)
 'C(key2)' (column 1)

当您在模型中使用多个分类项时,情况可能会更加复杂,因为您可以包括形式为key1:key2的交互项,例如在方差分析(ANOVA)模型中使用:

In [58]: data['key2'] = data['key2'].map({0: 'zero', 1: 'one'})
In [59]: data
Out[59]: 
 key1  key2  v1   v2
0    a  zero   1 -1.0
1    a   one   2  0.0
2    b  zero   3  2.5
3    b   one   4 -0.5
4    a  zero   5  4.0
5    b   one   6 -1.2
6    a  zero   7  0.2
7    b  zero   8 -1.7
In [60]: y, X = patsy.dmatrices('v2 ~ key1 + key2', data)
In [61]: X
Out[61]: 
DesignMatrix with shape (8, 3)
 Intercept  key1[T.b]  key2[T.zero]
 1          0             1
 1          0             0
 1          1             1
 1          1             0
 1          0             1
 1          1             0
 1          0             1
 1          1             1
 Terms:
 'Intercept' (column 0)
 'key1' (column 1)
 'key2' (column 2)
In [62]: y, X = patsy.dmatrices('v2 ~ key1 + key2 + key1:key2', data)
In [63]: X
Out[63]: 
DesignMatrix with shape (8, 4)
 Intercept  key1[T.b]  key2[T.zero]  key1[T.b]:key2[T.zero]
 1          0             1                       0
 1          0             0                       0
 1          1             1                       1
 1          1             0                       0
 1          0             1                       0
 1          1             0                       0
 1          0             1                       0
 1          1             1                       1
 Terms:
 'Intercept' (column 0)
 'key1' (column 1)
 'key2' (column 2)
 'key1:key2' (column 3)

Patsy 提供了其他转换分类数据的方法,包括具有特定顺序的项的转换。有关更多信息,请参阅在线文档。


Python 数据分析(PYDA)第三版(六)(2)https://developer.aliyun.com/article/1482397

相关文章
|
2天前
|
机器学习/深度学习 数据采集 算法
Python用逻辑回归、决策树、SVM、XGBoost 算法机器学习预测用户信贷行为数据分析报告
Python用逻辑回归、决策树、SVM、XGBoost 算法机器学习预测用户信贷行为数据分析报告
|
5天前
|
数据采集 数据可视化 数据挖掘
R语言与Python:比较两种数据分析工具
【4月更文挑战第25天】R语言和Python是目前最流行的两种数据分析工具。本文将对这两种工具进行比较,包括它们的历史、特点、应用场景、社区支持、学习资源、性能等方面,以帮助读者更好地了解和选择适合自己的数据分析工具。
|
11天前
|
机器学习/深度学习 数据挖掘 计算机视觉
python数据分析工具SciPy
【4月更文挑战第15天】SciPy是Python的开源库,用于数学、科学和工程计算,基于NumPy扩展了优化、线性代数、积分、插值、特殊函数、信号处理、图像处理和常微分方程求解等功能。它包含优化、线性代数、积分、信号和图像处理等多个模块。通过SciPy,可以方便地执行各种科学计算任务。例如,计算高斯分布的PDF,需要结合NumPy使用。要安装SciPy,可以使用`pip install scipy`命令。这个库极大地丰富了Python在科学计算领域的应用。
13 1
|
11天前
|
数据可视化 数据挖掘 Linux
python数据分析工具Seaborn
【4月更文挑战第15天】Seaborn是Python的数据可视化库,基于matplotlib,提供统计图形绘制。它包含内置数据集,支持风格控制和多种图形类型如散点图、分布图,擅长处理分类数据并能可视化统计估计。Seaborn还能绘制热图、聚类图及交互式图形。要使用它,先用`pip install seaborn`安装,然后导入并应用到数据集上,如示例中展示的散点图绘制。
10 1
|
12天前
|
数据可视化 数据挖掘 API
Python数据分析工具Seaborn
【4月更文挑战第14天】Seaborn是Python的数据可视化库,基于matplotlib,为数据科学家提供高级接口创建统计图形。其特点包括简洁的API、丰富的图形类型(如散点图、直方图)、内置统计功能、数据集集成和与pandas的紧密配合。使用时需先安装Seaborn和matplotlib,然后通过Seaborn的函数(如`scatterplot()`、`histplot()`)绘制图形。它是数据分析和可视化的一个强大工具。
21 8
Python数据分析工具Seaborn
|
12天前
|
数据可视化 数据挖掘 Python
Python中数据分析工具Matplotlib
【4月更文挑战第14天】Matplotlib是Python的数据可视化库,能生成多种图表,如折线图、柱状图等。以下是一个绘制简单折线图的代码示例: ```python import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [2, 4, 6, 8, 10] plt.figure() plt.plot(x, y) plt.title('简单折线图') plt.xlabel('X轴') plt.ylabel('Y轴') plt.show() ```
13 1
|
12天前
|
存储 数据挖掘 数据处理
Python中数据分析工具NumPy
【4月更文挑战第14天】NumPy是Python的数值计算扩展库,专注于处理大型多维数组和矩阵。其主要特性包括ndarray对象(存储同类型元素的高效数据容器)、广播机制(处理不同形状数组运算)、线性代数与统计函数、随机数生成及与C/C++/Fortran代码集成。作为Pandas等数据分析工具的基础,掌握NumPy对提升数据处理能力至关重要。
9 1
|
12天前
|
数据采集 SQL 数据可视化
Python数据分析工具Pandas
【4月更文挑战第14天】Pandas是Python的数据分析库,提供Series和DataFrame数据结构,用于高效处理标记数据。它支持从多种数据源加载数据,包括CSV、Excel和SQL。功能包括数据清洗(处理缺失值、异常值)、数据操作(切片、过滤、分组)、时间序列分析及与Matplotlib等库集成进行数据可视化。其高性能底层基于NumPy,适合大型数据集处理。通过加载数据、清洗、分析和可视化,Pandas简化了数据分析流程。广泛的学习资源使其成为数据分析初学者的理想选择。
15 1
|
20天前
|
数据采集 数据可视化 数据挖掘
深入浅出:使用Python进行数据分析
在这篇文章中,我们将探索Python在数据分析中的应用,介绍几个关键的库,如Pandas、NumPy、Matplotlib,以及如何使用它们进行有效的数据处理和可视化。本文旨在为初学者提供一个清晰、简洁的指南,让读者能够快速掌握使用Python进行数据分析的基本技能,并通过一个实例加深理解。不同于其他文章的冗长解释和复杂示例,我们将以最直接、易懂的方式,让你迅速上手,即使是完全没有编程背景的读者也能轻松跟上。
|
15天前
|
Python 数据挖掘 存储
Python 数据分析(PYDA)第三版(七)(4)
Python 数据分析(PYDA)第三版(七)
34 1