【问题标题】:Using ols function with parameters that contain numbers/spaces将 ols 函数与包含数字/空格的参数一起使用
【发布时间】:2019-01-10 06:14:00
【问题描述】:

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

       ols(formula,data).fit().rsquared_adj 

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

Q("weight.in.kg")

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

formula = "{} ~ {} + 1".format(response, ' + '.join([candidate])

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

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

Q('')

这样 ols 函数才能真正读取它? 抱歉,如果这非常明显,我不擅长 python。

【问题讨论】:

    标签: python list pandas charts patsy


    【解决方案1】:

    现在,您从公式中需要的术语列表开始,然后尝试将它们粘贴到一个复杂的字符串中,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')])])
    

    这可能看起来有点吓人,但实际上非常简单——你有一个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)
    

    现在您可以将 model_desc 对象传递给通常会传递 patsy 公式的任何函数:

    ols(model_desc, data).fit().rsquared_adj
    

    这里还有一个技巧:您会注意到第一个示例有 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))
    

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

    参考:

    【讨论】:

    • 您更高级的 Python 字符串处理并不完全正确:它有一对额外的括号。你想加入(引用)而不是。
    • 您需要在更高级的 Python 字符串处理中使用第二个 close-paren。
    猜你喜欢
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多