【问题标题】:Using categorical variables in statsmodels OLS class在 statsmodels OLS 类中使用分类变量
【发布时间】:2019-09-08 07:41:33
【问题描述】:

我想使用statsmodels OLS 类来创建多元回归模型。考虑以下数据集:

import statsmodels.api as sm
import pandas as pd
import numpy as np

dict = {'industry': ['mining', 'transportation', 'hospitality', 'finance', 'entertainment'],
  'debt_ratio':np.random.randn(5), 'cash_flow':np.random.randn(5) + 90} 

df = pd.DataFrame.from_dict(dict)

x = data[['debt_ratio', 'industry']]
y = data['cash_flow']

def reg_sm(x, y):
    x = np.array(x).T
    x = sm.add_constant(x)
    results = sm.OLS(endog = y, exog = x).fit()
    return results

当我运行以下代码时:

reg_sm(x, y)

我收到以下错误:

TypeError: '>=' not supported between instances of 'float' and 'str'

我尝试将 industry 变量转换为分类变量,但仍然出现错误。我别无选择。

【问题讨论】:

  • 这是因为 'industry' 是分类变量,但 OLS 需要数字(这可以从其源代码中看出)。删除行业,或按行业对数据进行分组并将 OLS 应用于每个组。

标签: python pandas statsmodels


【解决方案1】:

您在转换为分类 dtype 方面走在正确的道路上。但是,一旦将 DataFrame 转换为 NumPy 数组,就会得到一个 object dtype(NumPy 数组是一种整体的统一类型)。这意味着各个值仍然是 str 的基础,回归肯定不会喜欢。

你可能想做的是dummify这个功能。而不是 factorizing 它,它可以有效地将变量视为连续的,您希望保持一些类似的分类:

>>> import statsmodels.api as sm
>>> import pandas as pd
>>> import numpy as np
>>> np.random.seed(444)
>>> data = {
...     'industry': ['mining', 'transportation', 'hospitality', 'finance', 'entertainment'],
...    'debt_ratio':np.random.randn(5),
...    'cash_flow':np.random.randn(5) + 90
... }
>>> data = pd.DataFrame.from_dict(data)
>>> data = pd.concat((
...     data,
...     pd.get_dummies(data['industry'], drop_first=True)), axis=1)
>>> # You could also use data.drop('industry', axis=1)
>>> # in the call to pd.concat()
>>> data
         industry  debt_ratio  cash_flow  finance  hospitality  mining  transportation
0          mining    0.357440  88.856850        0            0       1               0
1  transportation    0.377538  89.457560        0            0       0               1
2     hospitality    1.382338  89.451292        0            1       0               0
3         finance    1.175549  90.208520        1            0       0               0
4   entertainment   -0.939276  90.212690        0            0       0               0

现在您有了 statsmodels 可以更好地使用的 dtypes。 drop_first 的目的是避免dummy trap

>>> y = data['cash_flow']
>>> x = data.drop(['cash_flow', 'industry'], axis=1)
>>> sm.OLS(y, x).fit()
<statsmodels.regression.linear_model.RegressionResultsWrapper object at 0x115b87cf8>

最后,只是一个小指针:它有助于尽量避免使用隐藏内置对象类型的名称来命名引用,例如 dict

【讨论】:

  • 作为使用pandas创建虚拟变量的替代方法,公式界面通过patsy自动转换字符串分类。
  • @Josef 你能详细说明如何(干净地)做到这一点吗?由于 Pandas 正在将任何字符串转换为 np.object。当我尝试使用带有某些列是字符串的 DataFrame 时,我得到了ValueError: Pandas data cast to numpy dtype of object. Check input data with np.asarray(data).
【解决方案2】:

我也遇到了这个问题,并且有很多列需​​要被视为分类,这使得处理dummify 非常烦人。并且转换为 string 对我不起作用。

对于寻求无需对数据进行 onehot 编码的解决方案的任何人, R 接口提供了一种很好的方法:

import statsmodels.formula.api as smf
import pandas as pd
import numpy as np

dict = {'industry': ['mining', 'transportation', 'hospitality', 'finance', 'entertainment'],
  'debt_ratio':np.random.randn(5), 'cash_flow':np.random.randn(5) + 90} 

df = pd.DataFrame.from_dict(dict)

x = df[['debt_ratio', 'industry']]
y = df['cash_flow']

# NB. unlike sm.OLS, there is "intercept" term is included here
smf.ols(formula="cash_flow ~ debt_ratio + C(industry)", data=df).fit()

参考: https://www.statsmodels.org/stable/example_formulas.html#categorical-variables

【讨论】:

  • 这种情况下如何用猫特征进行预测?
  • 应该和这里讨论的差不多。 statsmodels.org/stable/examples/notebooks/generated/…
  • 就个人而言,我会接受这个答案,它更干净(而且我不知道 R)!
  • 函数.get_prediction() 似乎不适用于此方法。我需要得到置信/预测区间。有没有办法用 smf r 语法做到这一点?
  • @OceanScientist 在最新版本的 statsmodels (v0.12.2) 中,.get_prediction() 方法有效。
猜你喜欢
  • 1970-01-01
  • 2019-04-14
  • 2020-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-06
  • 1970-01-01
  • 2019-09-07
相关资源
最近更新 更多