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