Repository: statsmodels/statsmodels

Issue:
NotImplementedError when fitting BinomialBayesMixedGLM.
Hi! When I try tu replicate the example given in the docs ([this one](http://www.statsmodels.org/dev/generated/statsmodels.genmod.bayes_mixed_glm.BinomialBayesMixedGLM.html#statsmodels.genmod.bayes_mixed_glm.BinomialBayesMixedGLM)) using a dataset with synthetic data I get a NotImplemented Error.
I'm using the 0.9.0 version As I said I used the exact same code and created a synthetic dataset.
Is there something wrong with the fit() method or am I doing something wrong?
Thanks!


Discussion:
try `fit_map` or `fit_vb`
it looks like `fit` is not defined in the model and it has just the inherited NotImplemented version

Resolving patch:
diff --git a/statsmodels/genmod/bayes_mixed_glm.py b/statsmodels/genmod/bayes_mixed_glm.py
--- a/statsmodels/genmod/bayes_mixed_glm.py
+++ b/statsmodels/genmod/bayes_mixed_glm.py
@@ -410,6 +410,14 @@ def from_formula(cls, formula, vc_formulas, data, family=None,
 
         return model
 
+    def fit(self, method="BFGS", minim_opts=None):
+        """
+        fit is equivalent to fit_map for this class.
+
+        See fit_map for parameter information.
+        """
+        self.fit_map(method, minim_opts)
+
     def fit_map(self, method="BFGS", minim_opts=None):
         """
         Construct the Laplace approximation to the posterior
@@ -447,6 +455,38 @@ def grad(params):
 
         return BayesMixedGLMResults(self, r.x, hess_inv, optim_retvals=r)
 
+    def predict(self, params, exog=None, linear=False):
+        """
+        Return the fitted mean structure.
+
+        Parameters
+        ----------
+        params : array-like
+            The parameter vector, may be the full parameter vector, or may
+            be truncated to include only the mean parameters.
+        exog : array-like
+            The design matrix for the mean structure.  If omitted, use the
+            model's design matrix.
+        linear : bool
+            If True, return the linear predictor without passing through the
+            link function.
+
+        Result
+        ------
+        A 1-dimensional array of predicted values
+        """
+
+        if exog is None:
+            exog = self.exog
+
+        q = exog.shape[1]
+        pr = np.dot(exog, params[0:q])
+
+        if not linear:
+            pr = self.family.link.inverse(pr)
+
+        return pr
+
 
 class _VariationalBayesMixedGLM(object):
     """
@@ -817,6 +857,26 @@ def random_effects(self, term=None):
 
         return x
 
+    def predict(self, exog=None, linear=False):
+        """
+        Return predicted values for the mean structure.
+
+        Parameters
+        ----------
+        exog : array-like
+            The design matrix for the mean structure.  If None,
+            use the model's design matrix.
+        linear : bool
+            If True, returns the linear predictor, otherwise
+            transform the linear predictor using the link function.
+
+        Returns
+        -------
+        A one-dimensional array of fitted values.
+        """
+
+        return self.model.predict(self.params, exog, linear)
+
 
 class BinomialBayesMixedGLM(_VariationalBayesMixedGLM, _BayesMixedGLM):
 


Test patch:
diff --git a/statsmodels/genmod/tests/test_bayes_mixed_glm.py b/statsmodels/genmod/tests/test_bayes_mixed_glm.py
--- a/statsmodels/genmod/tests/test_bayes_mixed_glm.py
+++ b/statsmodels/genmod/tests/test_bayes_mixed_glm.py
@@ -3,7 +3,7 @@
     BinomialBayesMixedGLM, PoissonBayesMixedGLM)
 import pandas as pd
 from scipy import sparse
-from numpy.testing import assert_allclose
+from numpy.testing import assert_allclose, assert_equal
 from scipy.optimize import approx_fprime
 
 
@@ -117,6 +117,16 @@ def test_simple_logit_map():
     assert_allclose(glmm.logposterior_grad(rslt.params),
                     np.zeros_like(rslt.params), atol=1e-3)
 
+    # Test the predict method
+    for linear in False, True:
+        for exog in None, exog_fe:
+            pr1 = rslt.predict(linear=linear, exog=exog)
+            pr2 = glmm.predict(rslt.params, linear=linear, exog=exog)
+            assert_allclose(pr1, pr2)
+            if not linear:
+                assert_equal(pr1.min() >= 0, True)
+                assert_equal(pr1.max() <= 1, True)
+
 
 def test_simple_poisson_map():
 
@@ -135,6 +145,21 @@ def test_simple_poisson_map():
     rslt2 = glmm2.fit_map()
     assert_allclose(rslt1.params, rslt2.params, atol=1e-4)
 
+    # Test the predict method
+    for linear in False, True:
+        for exog in None, exog_fe:
+            pr1 = rslt1.predict(linear=linear, exog=exog)
+            pr2 = rslt2.predict(linear=linear, exog=exog)
+            pr3 = glmm1.predict(rslt1.params, linear=linear, exog=exog)
+            pr4 = glmm2.predict(rslt2.params, linear=linear, exog=exog)
+            assert_allclose(pr1, pr2, rtol=1e-5)
+            assert_allclose(pr2, pr3, rtol=1e-5)
+            assert_allclose(pr3, pr4, rtol=1e-5)
+            if not linear:
+                assert_equal(pr1.min() >= 0, True)
+                assert_equal(pr2.min() >= 0, True)
+                assert_equal(pr3.min() >= 0, True)
+
 
 def test_crossed_logit_map():