Returns: - - - - model: an "optimal" fitted statsmodels linear model with an intercept selected by backward selection """ # begin with all factors and intercept possible_factors = set(data.columns) possible_factors.remove(response) formula = "{} ~ {} + 1".format(response, ' + '.join(possible_factors)) best_aic = sm.ols(formula, data).fit().aic current_aic = best_aic # create a non-empty set of columns that will be labeled as "to remove and try" to_try_remove = possible_factors # check which features remain while to_try_remove and current_aic == best_aic: aic_candidates = [] for candidate in to_try_remove: columns = possible_factors - set([candidate]) # removing the candidate column formula = "{} ~ {} + 1".format(response, ' + '.join(columns)) # print AIC aic = sm.ols(formula, data).fit().aic # append tuple of the form (aic, response) aic_candidates.append((aic, candidate)) # sort all the pairs by the first entry of tuple aic_candidates.sort() # change sort/pop order! best_new_aic, best_candidate = aic_candidates.pop(0) # check if we have something better: if best_new_aic < current_aic: # Remove the best candidate's name from possible_factors possible_factors.remove(best_candidate) current_aic = best_new_aic # repeat the process with all the remaining candidate columns