2015-06-20 103 views
1

我有一个数据框df与以下字段:weight,lengthanimal。前2个是连续变量,而animal是具有值cat,dogsnake的分类变量。评估statsmodels的具体类别的斜率和误差ols fit

我想估计重量和长度之间的关系,但这需要以动物的类型为条件,所以我将长度变量与animal分类变量相互作用。

model = ols(formula='weight ~ length * animal', data=df) 
results = model.fit() 

如何以编程方式提取重量和长度之间关系的斜率,例如,蛇?我了解如何手动执行此操作:将系数length添加到系数animal[T.snake]:length。但这有点繁琐和手动,并且需要我专门处理基本案例,所以我想自动提取这些信息。

此外,我想估计这个斜率的误差。我相信我理解如何通过结合标准误差和协方差(更准确地说,执行计算here)来计算这一点。但是这比上面更麻烦,我同样想知道是否有快捷方式来提取这些信息。

我的手动方法来计算这些如下。

编辑(2015年6月22日):我的原始代码似乎有一个错误,用于计算错误。 user333700的答案中计算的标准错误与我计算的不同,但我没有花时间去弄清楚为什么。

def get_contained_animal(animals, p): 
    # This relies on parameters of the form animal[T.snake]:length. 
    for a in animals: 
     if a in p: 
      return a 
    return None 

animals = ['cat', 'dog', 'snake'] 
slopes = {} 
errors = {} 
for animal in animals: 
    slope = 0. 
    params = [] 
    # If this param is related to the length variable and 
    # the animal in question, add it to the slope. 
    for param, val in results.params.iteritems(): 
     ac = get_contained_animal(animals, param) 
     if (param == 'length' or 
      ('length' in param and 
      ac is None or ac == animal)): 
      params.append(param) 
      slope += val 

    # Calculate the overall error by adding standard errors and 
    # covariances. 
    tot_err = 0. 
    for i, p1 in enumerate(params): 
     tot_err += results.bse[p1]*results.bse[p1] 
     for j, p2 in enumerate(params[i:]): 
      # add covariance of these parameters 
      tot_err += 2*results.cov_params()[p1][p2] 

    slopes[animal] = slope 
    errors[animal] = tot_err**0.5 

此代码似乎有点小题大做,但在我的实际使用情况下,我有一个连续变量有两个单独的分类变量,每一个门类众多的相互作用(与模型中的其他条款沿我需要忽略这些目的)。

+0

标准误差公式对于两个参数总和的情况看起来是正确的。但是,我认为在标准误差计算中不会选择与“斜率”计算相对应的'params'。另外,这个计算不会轻易地推广到其他情况,而不是两个参数的总和。 – user333700

回答

2

非常简要背景:

这种情况的一般问题是怎么做,如果我们改变对解释变量,持股不动或平均比那些其他解释变量的预测变化。

在非线性离散模型中,有一种特殊的Margins方法可以计算这种方法,虽然它不适用于分类变量的变化。

在线性模型中,预测和预测变化只是估计参数的线性函数,我们可以(误)使用t_test来计算效应,它的标准误差和置信区间。

(旁白:有更多的辅助方法在作品statsmodels做出预测和保证金计算这样更容易,将可极有可能在今年晚些时候推出。)下面的代码的

随着简要说明:

  • 我构成了一个类似的例子。
  • 我定义的解释性变量长度= 1或2,对于每个动物类型
  • 然后,我计算在这些解释性变量
  • 这定义的线性组合或者参数的对比度的差,可在t_test使用。

最后,我比较预测的结果,检查我没有犯任何明显的错误。 (我认为这是正确的,但我写这非常快。)

import numpy as np 
import pandas as pd 

from statsmodels.regression.linear_model import OLS 

np.random.seed(2) 
nobs = 20 
animal_names = np.array(['cat', 'dog', 'snake']) 
animal_idx = np.random.random_integers(0, 2, size=nobs) 
animal = animal_names[animal_idx] 
length = np.random.randn(nobs) + animal_idx 
weight = np.random.randn(nobs) + animal_idx + length 

data = pd.DataFrame(dict(length=length, weight=weight, animal=animal)) 

res = OLS.from_formula('weight ~ length * animal', data=data).fit() 
print(res.summary()) 


data_predict1 = data = pd.DataFrame(dict(length=np.ones(3), weight=np.ones(3), 
             animal=animal_names)) 

data_predict2 = data = pd.DataFrame(dict(length=2*np.ones(3), weight=np.ones(3), 
             animal=animal_names)) 

import patsy 
x1 = patsy.dmatrix('length * animal', data_predict1) 
x2 = patsy.dmatrix('length * animal', data_predict2) 

tt = res.t_test(x2 - x1) 
print(tt.summary(xname=animal_names.tolist())) 

最后一次打印的结果是

       Test for Constraints        
============================================================================== 
       coef std err   t  P>|t|  [95.0% Conf. Int.] 
------------------------------------------------------------------------------ 
cat   1.0980  0.280  3.926  0.002   0.498  1.698 
dog   0.9664  0.860  1.124  0.280  -0.878  2.811 
snake   1.5930  0.428  3.720  0.002   0.675  2.511 

我们可以通过预测和比较的预测的差异验证结果重量如果长度对于给定的动物类型从1增加到2:

>>> [res.predict({'length': 2, 'animal':[an]}) - res.predict({'length': 1, 'animal':[an]}) for an in animal_names] 
[array([ 1.09801656]), array([ 0.96641455]), array([ 1.59301594])] 
>>> tt.effect 
array([ 1.09801656, 0.96641455, 1.59301594]) 

注:I忘了添加的晶种的随机数和数字不能被复制。

+0

注意:编辑添加种子不起作用。它需要在包 – user333700

+0

中使用numpy的'np.random.seed'而不是python的'random' build。很对 - 这是我的懒惰。建议编辑新建。谢谢! – abeboparebop

+0

新编辑看起来不错,但我没有找到批准它的方法。 – user333700