Использование функции ols с параметрами, содержащими цифры / пробелы

У меня много трудностей с использованием функции 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])

с [кандидатом] быть моим списком предикторов.

Мой вопрос к вам, дорогие эксперты по питону, как я могу поместить каждый отдельный элемент в списке [кандидат] в кавычки в следующем выражении:

Q ('')

так что функция ols действительно может прочитать? Извинения, если это супер очевидно, я не хорош в питоне.

1 ответ

Прямо сейчас вы начинаете со списка терминов, которые вы хотите в своей формуле, а затем пытаетесь вставить их вместе в сложную строку, которая будет проанализирована и преобразована обратно в список терминов. Вы можете увидеть структуру данных, которую генерирует patsy для такой формулы (ModelDesc.from_formula парсера парси)

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([]) как пси представляет символ перехвата.

Таким образом, вы можете избежать всего этого сложного цитирования / разбора, напрямую создавая нужные вам термины и передавая их в простую строку, пропуская шаг разбора строки

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 объект в любую функцию, где вы обычно передаете формулу

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-файл) - вы можете получить все виды выполнения произвольного кода. Приведенное выше решение позволяет избежать всех этих проблем.

Ссылка:

Другие вопросы по тегам