利用Python进行数据分析笔记-pandas建模(Patsy篇)

跟着教程学习了一段时间数据分析,越学感觉坑越多。于是花了一个星期仔细看了下《利用Python进行数据分析》。写在这里主要是记录下,方便自己查看。

import numpy as np
import pandas as pd
import patsy
# 利用Patsy创建模型描述 Patsy是一个python库,用于描述统计模型(尤其是线性模型),方法是通过一个叫做公式语法(formula syntax)的字符串来描述。这种公式语法的灵感来源于R和S语言中的公式语法。 Patsy的公式是有特殊格式的字符串,像下面这样: y ~ x0 + x1 这种a + b的语法并不代表将a和b相加,而是代表为模型创建的设计矩阵的术语(terms in the design matrix)。patsy.dmatrices函数,取一个公式字符串和一个数据集(可以使DataFrame或dict),然后为线性模型产生设计矩阵:
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.]})
data
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
y, X = patsy.dmatrices('y ~ x0 + x1', data)
y
DesignMatrix with shape (5, 1)
     y
  -1.5
   0.0
   3.6
   1.3
  -2.0
  Terms:
    'y' (column 0)
X
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,附有额外的元数据(metadata)

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

我们可能奇怪X中的Intercept是从哪里来的。这其实是线性模型的一个惯例,比如普通最小二乘回归法(ordinary least squares regression)。我们可以去掉这个截距(intercept),通过加添术语+0给模型

patsy.dmatrices('y ~ x0 + x1 + 0', data)[1]
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,来进行普通最小二乘回归的计算

# 最小二乘法
coef, resid, _, _ = np.linalg.lstsq(X, y, rcond=-1)
coef
array([[ 0.31290976],
       [-0.07910564],
       [-0.26546384]])
coef = pd.Series(coef.squeeze(), index=X.design_info.column_names)
coef
Intercept    0.312910
x0          -0.079106
x1          -0.265464
dtype: float64

1、Patsy公式的数据变换

我们可以把python和Patsy公式混合起来。当评估公式的时候,库会尝试找到封闭域中的公式:

y, X = patsy.dmatrices('y ~ x0 + np.log(np.abs(x1) + 1)', data)
X
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)

一些常用的变量变换,包括标准化(standardizing (平均值0,方差1)和中心化(减去平均值)。Patsy有内建的函数可以做到这些

y, X = patsy.dmatrices('y ~ standardize(x0) + center(x1)', data)
X
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)
    'center(x1)' (column 2)

作为建模的一部分,我们可能会在一个数据及上训练模型,然后在另一个数据及上评价模型。当使用中心化或标准化这样的转换时,我们必须注意,必须用模型在新数据集上做预测。这叫做状态变换(stateful transformations)。因为我们必须用原本在训练集上得到的平均值和标准差,用在新的数据集上。

通过保存原先数据集中的信息,patsy.build_design_matrices函数能把变换用在新的数据集上

new_data = pd.DataFrame({
        'x0': [6, 7, 8, 9], 
        'x1': [3.1, -0.5, 0, 2.3],
        'y': [1, 2, 3, 4]})
new_X = patsy.build_design_matrices([X.design_info], new_data)
new_X
[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函数包起来

y, X = patsy.dmatrices('y ~ I(x0 + x1)', data)
X
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模块里。更多的信息请参考文档。

Categorical数据有特殊的类用于变换,下面进行介绍。

2、Categorical数据和Patsy

非数值型数据可以通过很多种方式变为一个模型设计矩阵。这个话题很大,这里只做简单介绍。

当我们在Patsy公式中使用非数值术语时,这些类型数据默认会被转换为哑变量。如果有截距,一个层级上的截距会被舍弃,防止出现共线性:

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] })
y, X = patsy.dmatrices('v2 ~ key1', data)
X
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)

如果从模型中舍弃截距,每个类型的列会被包含在模型设计矩阵中

y, X = patsy.dmatrices('v2 ~ key1 + 0', data)
X
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函数,变为类型列:

y, X = patsy.dmatrices('v2 ~ C(key2)', data)
X
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的形式来包含有交集的术语,这种方法可以用于使用多个术语,例如,一个方法分析模型(analysis of variance (ANOVA) models):

data['key2'] = data['key2'].map({0: 'zero', 1: 'one'})
data
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
y, X = patsy.dmatrices('v2 ~ key1 + key2', data)
X
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)
y, X = patsy.dmatrices('v2 ~ key1 + key2 + key1:key2', data)
X
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)

你可能感兴趣的:(数据分析,利用Python进行数据分析,利用Python进行数据分析)