本系列文章配套代码获取有以下三种途径:
-
可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):
https://returu.github.io/Python_Data_Analysis/lab/index.html
-
也可以通过百度网盘获取,需要在本地配置代码运行环境,环境配置可以查看【Python基础】2.搭建Python开发环境:
链接:https://pan.baidu.com/s/1MYkeYeVAIRqbxezQECHwcA?pwd=mnsj
提取码:mnsj
-
前往GitHub详情页面,单击 code 按钮,选择Download ZIP选项:
https://github.com/returu/Python_Data_Analysis
根据《Python for Data Analysis 3rd Edition》翻译整理
—————————————————–
Patsy(https://patsy.readthedocs.io/en/latest/) 是一个Python库,用于描述统计模型(特别是线性模型),使用一种小型的基于字符串的“公式语法”,该语法受到R和S统计编程语言中使用的公式语法的启发(但不完全相同)。在你安装statsmodels时会自动安装Patsy。
使用conda安装statsmodels:conda install statsmodels
Patsy对于statsmodels中指特定的线性模型有很好的支持,所以将重点介绍它的一些主要的功能,以帮助你启动和运行程序。Patsy的公式是一种特殊的字符串语法,例如:y ~ x0 + x1。
语法a+b并不是指将a加到b上,而是指为模型而创建的设计矩阵中的名词列。patsy.dmatrices函数接收一个公式字符串和一个数据集(可以是一个DataFrame或数组字典),并产生线性模型的设计矩阵。
1>>> data = pd.DataFrame({'x0': [1, 2, 3, 4, 5],'x1': [1, -2, 3, -4, 0],'y': [-15, 0, 35, 15, -20]})
2>>> data
3 x0 x1 y
40 1 1 -15
51 2 -2 0
62 3 3 35
73 4 -4 15
84 5 0 -20
9
10>>> y, X = patsy.dmatrices('y ~ x0 + x1', data)
11
12>>> y
13DesignMatrix with shape (5, 1)
14 y
15-15
16 0
17 35
18 15
19-20
20Terms:
21'y' (column 0)
22
23>>> X
24DesignMatrix with shape (5, 3)
25Intercept x0 x1
26 1 1 1
27 1 2 -2
28 1 3 3
29 1 4 -4
30 1 5 0
31Terms:
32'Intercept' (column 0), 'x0' (column 1), 'x1' (column 2)
这些 Patsy 的 DesignMatrix 实例是带有额外元数据的NumPy ndarray。
1>>> np.asarray(y)
2array([[-15.],
3 [ 0.],
4 [ 35.],
5 [ 15.],
6 [-20.]])
7
8>>> np.asarray(X)
9array([[ 1., 1., 1.],
10 [ 1., 2., -2.],
11 [ 1., 3., 3.],
12 [ 1., 4., -4.],
13 [ 1., 5., 0.]])
输出结果中的 Intercept(截距 )是普通最小二乘法(OLS)回归等线性模型中的惯例。你可以通过在模型中加入名词列 +0 来抑制截距。
1>>> patsy.dmatrices('y ~ x0 + x1 + 0', data)[1]
2DesignMatrix with shape (5, 2)
3x0 x1
4 1 1
5 2 -2
6 3 3
7 4 -4
8 5 0
9Terms:
10'x0' (column 0), 'x1' (column 1)
Patsy对象可以直接传递给numpy.linalg.lstsq等算法,这些算法都会执行一个最小二乘回归。
模型元数据保留在 design_info 属性中,因此你可以将模型列名重新附加到拟合系数上,以获得一个Series。
1>>> coef, resid, _, _ = np.linalg.lstsq(X, y , rcond=-1)
2
3>>> coef
4array([[0.39855072],
5 [1.05072464],
6 [1.37681159]])
7
8>>> resid
9array([1975.18115942])
10
11>>> coef = pd.Series(coef.squeeze(), index=X.design_info.column_names)
12>>> coef
13Intercept 0.398551
14x0 1.050725
15x1 1.376812
16dtype: float64
你可以将Python代码混入你的Patsy公式中;当执行公式时,Patsy会尝试在封闭作用域中寻找你使用的函数。
1>>> y, X = patsy.dmatrices('y ~ x0 + np.log(np.abs(x1) + 1)', data)
2
3>>> X
4DesignMatrix with shape (5, 3)
5Intercept x0 np.log(np.abs(x1) + 1)
6 1 1 0.69315
7 1 2 1.09861
8 1 3 1.38629
9 1 4 1.60944
10 1 5 0.00000
11Terms:
12'Intercept' (column 0), 'x0' (column 1), 'np.log(np.abs(x1) + 1)' (column 2)
一些常用的变量转换包括标准化(均值为0,方差为1)和居中(减去平均值)。Patsy库有内置的函数来实现这一目的。
1>>> y, X = patsy.dmatrices('y ~ standardize(x0) + center(x1)', data)
2
3>>> X
4DesignMatrix with shape (5, 3)
5Intercept standardize(x0) center(x1)
6 1 -1.41421 1.4
7 1 -0.70711 -1.6
8 1 0.00000 3.4
9 1 0.70711 -3.6
10 1 1.41421 0.4
11Terms:
12'Intercept' (column 0), 'standardize(x0)' (column 1), 'center(x1)' (column 2)
作为建模过程的一部分,你可能在一个数据集上拟合一个模型,然后根据另一个数据集来评估该模型。这个过程可以保留部分数据或者之后再加入新数据。当应用像居中和标准化这样的转换时,在使用基于新数据使用模型进行预测时要小心。这些转换被称为有状态的转换,因为在转换新的数据集时,必须使用原始数据集的均值或标准差等统计数据。
patsy.build_design_matrices函数可以使用原始样本内数据集中保存的信息将变换应用于新的样本外数据上:
1>>> new_data = pd.DataFrame({'x0': [6, 7, 8, 9],'x1': [3, -0.5, 0, 2],'y': [1, 2, 3, 4]})
2>>> new_data
3 x0 x1 y
40 6 3.0 1
51 7 -0.5 2
62 8 0.0 3
73 9 2.0 4
8
9>>> new_X = patsy.build_design_matrices([X.design_info], new_data)
10
11>>> new_X
12[DesignMatrix with shape (4, 3)
13Intercept standardize(x0) center(x1)
14 1 2.12132 3.4
15 1 2.82843 -0.1
16 1 3.53553 0.4
17 1 4.24264 2.4
18Terms:
19'Intercept' (column 0), 'standardize(x0)' (column 1), 'center(x1)' (column 2)]
因为加号(+)在Patsy公式的上下文中并不意味着加法,当你想对数据集中两列按列名相加,你必须用特殊的 I 函数来封装。
1>>> y, X = patsy.dmatrices('y ~ I(x0 + x1)', data)
2>>> X
3DesignMatrix with shape (5, 2)
4Intercept I(x0 + x1)
5 1 2
6 1 0
7 1 6
8 1 0
9 1 5
10Terms:
11'Intercept' (column 0), 'I(x0 + x1)' (column 1)
在patsy.buildins模块中,Patsy还有其他一些内置的转换功能。更多内容请参见在线文档。
非数字类型数据可以通过许多不同的方式将其转换为用于模型的设计矩阵。对这一内容的完整处理超出了本文的范围,最好是能够学习一门统计学课程。
当你在Patsy公式中使用非数字名词列时,它们会被默认转换为虚拟变量。如果有一个拦截,其中一个级别将会被排除,以避免共线性。
1>>> data = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a', 'b', 'a', 'b'],
2... 'key2': [0, 1, 0, 1, 0, 1, 0, 0],
3... 'v1': [1, 2, 3, 4, 5, 6, 7, 8],
4... 'v2': [-1, 0, 2, -5, 4, -1, 2, -3]})
5
6>>> data
7 key1 key2 v1 v2
80 a 0 1 -1
91 a 1 2 0
102 b 0 3 2
113 b 1 4 -5
124 a 0 5 4
135 b 1 6 -1
146 a 0 7 2
157 b 0 8 -3
16
17>>> y, X = patsy.dmatrices('v2 ~ key1', data)
18
19>>> X
20DesignMatrix with shape (8, 2)
21Intercept key1[T.b]
22 1 0
23 1 0
24 1 1
25 1 1
26 1 0
27 1 1
28 1 0
29 1 1
30Terms:
31'Intercept' (column 0), 'key1' (column 1)
如果你忽略了模型中的截距,那么每个类别值的列将被包括在模型的设计矩阵中。
1>>> y, X = patsy.dmatrices('v2 ~ key1 + 0', data)
2>>> X
3DesignMatrix with shape (8, 2)
4key1[a] key1[b]
5 1 0
6 1 0
7 0 1
8 0 1
9 1 0
10 0 1
11 1 0
12 0 1
13Terms:
14'key1' (columns 0:2)
数值列可以用 C 函数解释为分类列。
1>>> y, X = patsy.dmatrices('v2 ~ C(key2)', data)
2>>> X
3DesignMatrix with shape (8, 2)
4Intercept C(key2)[T.1]
5 1 0
6 1 1
7 1 0
8 1 1
9 1 0
10 1 1
11 1 0
12 1 0
13Terms:
14'Intercept' (column 0), 'C(key2)' (column 1)
当你在一个模型中使用多个分类名词列时,事情可能会更复杂,因为你可以包括形式为key1:key2的交互项,例如,可以用于方差分析(ANOVA)模型。
1>>> data['key2'] = data['key2'].map({0: 'zero', 1: 'one'})
2>>> data
3 key1 key2 v1 v2
40 a zero 1 -1
51 a one 2 0
62 b zero 3 2
73 b one 4 -5
84 a zero 5 4
95 b one 6 -1
106 a zero 7 2
117 b zero 8 -3
12
13>>> y, X = patsy.dmatrices('v2 ~ key1 + key2', data)
14>>> X
15DesignMatrix with shape (8, 3)
16Intercept key1[T.b] key2[T.zero]
17 1 0 1
18 1 0 0
19 1 1 1
20 1 1 0
21 1 0 1
22 1 1 0
23 1 0 1
24 1 1 1
25Terms:
26'Intercept' (column 0), 'key1' (column 1), 'key2' (column 2)
27
28
29>>> y, X = patsy.dmatrices('v2 ~ key1 + key2 + key1:key2', data)
30>>> X
31DesignMatrix with shape (8, 4)
32Intercept key1[T.b] key2[T.zero] key1[T.b]:key2[T.zero]
33 1 0 1 0
34 1 0 0 0
35 1 1 1 1
36 1 1 0 0
37 1 0 1 0
38 1 1 0 0
39 1 0 1 0
40 1 1 1 1
41Terms:
42'Intercept' (column 0), 'key1' (column 1), 'key2' (column 2), 'key1:key2' (column 3)
Patsy还提供了其他转换分类数据的方法,包括按照特定排序对名词列进行转换。更多信息请参见官方文档。
本篇文章来源于微信公众号: 码农设计师