diff --git a/statsmodels/examples/ex_ordered_model.py b/statsmodels/examples/ex_ordered_model.py index b06c3c569ae..cf99a82e128 100644 --- a/statsmodels/examples/ex_ordered_model.py +++ b/statsmodels/examples/ex_ordered_model.py @@ -24,7 +24,7 @@ print(np.bincount(y)) mod = OrderedModel(y, x) -start_params = np.ones(k_vars + 4) +# start_params = np.ones(k_vars + 4) start_params = np.concatenate((np.ones(k_vars), np.arange(4))) start_ppf = stats.norm.ppf((np.bincount(y) / len(y)).cumsum()) start_threshold = np.concatenate((start_ppf[:1], diff --git a/statsmodels/miscmodels/ordinal_model.py b/statsmodels/miscmodels/ordinal_model.py index 94ea42da8f4..c0922dad0bd 100644 --- a/statsmodels/miscmodels/ordinal_model.py +++ b/statsmodels/miscmodels/ordinal_model.py @@ -118,7 +118,7 @@ def _check_inputs(self, endog, exog): exog_name = ([exog.name] if isinstance(exog, pd.Series) else exog.columns.tolist()) names['xname'] = exog_name - exog = np.asarray(exog) + # exog = np.asarray(exog) if isinstance(endog, pd.Series): if isinstance(endog.dtypes, CategoricalDtype): @@ -315,6 +315,22 @@ def fit(self, start_params=None, method='nm', maxiter=500, full_output=1, class OrderedResults(GenericLikelihoodModelResults): + + def pred_table(self): + """prediction table + + returns pandas DataFrame + + """ + # todo: add category labels + categories = np.arange(self.model.k_levels) + observed = pd.Categorical(self.model.endog, + categories=categories, ordered=True) + predicted = pd.Categorical(self.predict().argmax(1), + categories=categories, ordered=True) + table = pd.crosstab(observed, predicted, margins=True, dropna=False) + return table + @Appender(GenericLikelihoodModelResults.summary.__doc__) def summary(self, yname=None, xname=None, title=None, alpha=.05): names = self.model.names diff --git a/statsmodels/miscmodels/tests/results/__init__.py b/statsmodels/miscmodels/tests/results/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/statsmodels/miscmodels/tests/test_ordinal_model.py b/statsmodels/miscmodels/tests/test_ordinal_model.py index 7e4ecf4a027..28e14403660 100644 --- a/statsmodels/miscmodels/tests/test_ordinal_model.py +++ b/statsmodels/miscmodels/tests/test_ordinal_model.py @@ -5,7 +5,7 @@ import numpy as np import scipy.stats as stats -from numpy.testing import assert_allclose +from numpy.testing import assert_allclose, assert_equal from .results.results_ordinal_model import data_store as ds from statsmodels.miscmodels.ordinal_model import OrderedModel @@ -70,6 +70,27 @@ def test_unordered(self): assert_allclose(res1.model.endog, resf.model.endog, rtol=1e-10) assert_allclose(res1.model.exog, resf.model.exog, rtol=1e-10) + def test_results_other(self): + + res1 = self.res1 + + # results + if hasattr(self, "pred_table"): + table = res1.pred_table() + assert_equal(table.values, self.pred_table) + + # smoke test + res1.summary() + + # inherited + tt = res1.t_test(np.eye(len(res1.params))) + assert_allclose(tt.pvalue, res1.pvalues, rtol=1e-13) + # TODO: test using string definition of constraints + + pred = res1.predict(exog=res1.model.exog[-5:]) + fitted = res1.predict() + assert_allclose(pred, fitted[-5:], rtol=1e-13) + class TestLogitModel(CheckOrdinalModelMixin): @@ -151,6 +172,12 @@ def setup_class(cls): cls.resf = resf cls.resu = resu + # regression numbers + cls.pred_table = np.array([[202, 18, 0, 220], + [112, 28, 0, 140], + [ 27, 13, 0, 40], # noqa + [341, 59, 0, 400]], dtype=np.int64) + def test_loglikerelated(self): res1 = self.res1 @@ -161,8 +188,8 @@ def test_loglikerelated(self): score1 = mod.score(res1.params * fact) score_obs_numdiff = mod.score_obs(res1.params * fact) score_obs_exog = mod.score_obs_(res1.params * fact) - assert_allclose(score_obs_numdiff.sum(0), score1, rtol=1e-8) - assert_allclose(score_obs_exog.sum(0), score1[:mod.k_vars], rtol=1e-7) + assert_allclose(score_obs_numdiff.sum(0), score1, atol=1e-7) + assert_allclose(score_obs_exog.sum(0), score1[:mod.k_vars], atol=1e-7) # null model mod_null = OrderedModel(mod.endog, None,