为 statsmodels ols fit 评估特定类别的斜率和误差
Evaluate slope and error for specific category for statsmodels ols fit
我有一个包含以下字段的数据框 df
:weight
、length
和 animal
。前 2 个是连续变量,而 animal
是一个分类变量,其值为 cat
、dog
和 snake
.
我想估计体重和长度之间的关系,但这需要以动物的类型为条件,所以我将长度变量与 animal
分类变量进行交互。
model = ols(formula='weight ~ length * animal', data=df)
results = model.fit()
如何以编程方式提取重量和长度之间关系的斜率,例如蛇?我知道如何手动执行此操作:将 length
的系数添加到 animal[T.snake]:length
的系数。但这有点麻烦和手动,需要我专门处理基本情况,所以我想自动提取这些信息。
此外,我想估计这个斜率的误差。我相信我了解如何通过结合标准误差和协方差来计算它(更准确地说,执行计算 here)。但这比上面的还要麻烦,我同样想知道是否有提取这些信息的捷径
我的手动计算方法如下。
编辑 (06/22/2015):我下面的原始代码似乎有错误计算错误。 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
这段代码可能看起来有点矫枉过正,但在我的实际用例中,我有一个连续变量与两个独立的分类变量交互,每个分类变量都有大量类别(以及我需要的模型中的其他项)为了这些目的而忽略)。
非常简短的背景:
这个问题的一般问题是,如果我们改变解释变量,保持其他解释变量固定或对这些变量进行平均,预测会如何变化。
在非线性离散模型中,有一种特殊的 Margins 方法可以计算它,尽管它没有针对分类变量的变化实现。
在线性模型中,预测和预测的变化只是估计参数的线性函数,我们可以(误)使用t_test
来计算效果,其标准误差和置信区间我们.
(旁白:statsmodels 的工作中有更多的辅助方法可以使这样的预测和保证金计算更容易,并且很可能在今年晚些时候提供。)
作为下面代码的简单解释:
- 我编了一个类似的例子。
- 我为每种动物类型定义了长度 = 1 或 2 的解释变量
- 然后,我计算这些解释变量的差异
- 这定义了参数的线性组合或对比,可用于 t_test。
最后,我与 predict 的结果进行了比较,以检查我没有犯任何明显的错误。 (我认为这是正确的,但我写得相当快。)
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,我们可以使用 predict 和比较预测重量的差异来验证结果:
>>> [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])
注意:随机数忘了加种子,随机数无法复制
我有一个包含以下字段的数据框 df
:weight
、length
和 animal
。前 2 个是连续变量,而 animal
是一个分类变量,其值为 cat
、dog
和 snake
.
我想估计体重和长度之间的关系,但这需要以动物的类型为条件,所以我将长度变量与 animal
分类变量进行交互。
model = ols(formula='weight ~ length * animal', data=df)
results = model.fit()
如何以编程方式提取重量和长度之间关系的斜率,例如蛇?我知道如何手动执行此操作:将 length
的系数添加到 animal[T.snake]:length
的系数。但这有点麻烦和手动,需要我专门处理基本情况,所以我想自动提取这些信息。
此外,我想估计这个斜率的误差。我相信我了解如何通过结合标准误差和协方差来计算它(更准确地说,执行计算 here)。但这比上面的还要麻烦,我同样想知道是否有提取这些信息的捷径
我的手动计算方法如下。
编辑 (06/22/2015):我下面的原始代码似乎有错误计算错误。 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
这段代码可能看起来有点矫枉过正,但在我的实际用例中,我有一个连续变量与两个独立的分类变量交互,每个分类变量都有大量类别(以及我需要的模型中的其他项)为了这些目的而忽略)。
非常简短的背景:
这个问题的一般问题是,如果我们改变解释变量,保持其他解释变量固定或对这些变量进行平均,预测会如何变化。
在非线性离散模型中,有一种特殊的 Margins 方法可以计算它,尽管它没有针对分类变量的变化实现。
在线性模型中,预测和预测的变化只是估计参数的线性函数,我们可以(误)使用t_test
来计算效果,其标准误差和置信区间我们.
(旁白:statsmodels 的工作中有更多的辅助方法可以使这样的预测和保证金计算更容易,并且很可能在今年晚些时候提供。)
作为下面代码的简单解释:
- 我编了一个类似的例子。
- 我为每种动物类型定义了长度 = 1 或 2 的解释变量
- 然后,我计算这些解释变量的差异
- 这定义了参数的线性组合或对比,可用于 t_test。
最后,我与 predict 的结果进行了比较,以检查我没有犯任何明显的错误。 (我认为这是正确的,但我写得相当快。)
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,我们可以使用 predict 和比较预测重量的差异来验证结果:
>>> [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])
注意:随机数忘了加种子,随机数无法复制