将 ols 函数与包含数字/空格的参数一起使用

Tho*_*mas 5 python charts list pandas patsy

我在使用 statsmodels.formula.api 函数时遇到很多困难

       ols(formula,data).fit().rsquared_adj 
Run Code Online (Sandbox Code Playgroud)

由于我的预测者的名字的性质。预测变量中有数字和空格等,这显然是它不喜欢的。我知道我需要使用 patsy.builtins.Q 之类的东西,所以假设我的预测变量是 Weight.in.kg ,它应该输入如下:

Q("weight.in.kg")
Run Code Online (Sandbox Code Playgroud)

所以我需要从列表中获取公式,并且使用 patsy.builtin.Q 修改列表中的每个项目会出现困难

formula = "{} ~ {} + 1".format(response, ' + '.join([candidate])
Run Code Online (Sandbox Code Playgroud)

[候选者] 是我的预测变量列表。

我向您提出的问题是,最亲爱的 Python 专家,我到底如何将列表 [candidate] 中的每个单独项目放在以下表达式的引号内:

问('')

这样 ols 函数就能真正读取它吗?如果这太明显了,我很抱歉,我不擅长 python。

Nat*_*ith 4

现在,您从公式中所需的术语列表开始,然后尝试将它们粘贴到一个复杂的字符串中,patsy 将解析该字符串并将其转换回术语列表。你可以看到 patsy 为这种公式生成的数据结构(ModelDesc.from_formula是 patsy 的解析器):

In [7]: from patsy import ModelDesc

In [8]: ModelDesc.from_formula("y ~ x1 + x2 + x3")
Out[8]: 
ModelDesc(lhs_termlist=[Term([EvalFactor('y')])],
          rhs_termlist=[Term([]),
                        Term([EvalFactor('x1')]),
                        Term([EvalFactor('x2')]),
                        Term([EvalFactor('x3')])])
Run Code Online (Sandbox Code Playgroud)

这可能看起来有点吓人,但实际上非常简单 - 您有一个ModelDesc,它代表一个公式,并且它有一个左侧术语列表和一个右侧术语列表。每个术语都由一个对象表示Term,并且每个Term术语都有一个因素列表。(这里每个项只有一个因子 - 如果您有任何交互作用,那么这些项将具有多个因子。)此外,“空交互”Term([])是 patsy 表示截距项的方式。

因此,您可以通过直接创建所需的术语并将它们传递给 patsy 来避免所有这些复杂的引用/解析内容,跳过字符串解析步骤

from patsy import ModelDesc, Term, LookupFactor

response_terms = [Term([LookupFactor(response)])]
# start with intercept...
model_terms = [Term([])]
# ...then add another term for each candidate
model_terms += [Term([LookupFactor(c)]) for c in candidates]
model_desc = ModelDesc(response_terms, model_terms)
Run Code Online (Sandbox Code Playgroud)

现在您可以将该model_desc对象传递到通常传递 Patsy 公式的任何函数中:

ols(model_desc, data).fit().rsquared_adj
Run Code Online (Sandbox Code Playgroud)

这里还有另一个技巧:您会注意到第一个示例有EvalFactor对象,而现在我们正在使用LookupFactor对象。不同之处在于,它EvalFactor需要一串任意的Python代码,如果你想写类似的东西np.log(x1),这很好,但如果你有像这样的变量,那就很烦人了weight.in.kg。LookupFactor直接获取变量的名称来在数据中查找,因此不需要进一步引用。

或者,您可以使用一些更高级的 Python 字符串处理来完成此操作,例如:

quoted = ["Q('{}')".format(c) for c in candidates]
formula = "{} ~ {} + 1".format(response, ' + '.join(quoted))
Run Code Online (Sandbox Code Playgroud)

但是,虽然一开始比较简单,但它却更加脆弱 - 例如,考虑(或尝试)如果您的参数之一包含引号字符会发生什么!您永远不应该在候选名称来自您无法控制的其他地方(例如随机 CSV 文件)的处理管道中编写类似的内容 - 您可能会执行各种任意代码。上述解决方案避免了所有这些问题。

参考: