Repository: statsmodels/statsmodels

Issue:
Undefined attribute _bw_method causes KDEMultivariate.__repr__ to crash.
If user does not provide `bw` to `KDEMultivariate.__init__`, when [`self._compute_bw(bw)`](https://github.com/statsmodels/statsmodels/blob/master/statsmodels/nonparametric/kernel_density.py#L116) is invoked, the [`GenericKDE._compute_bw`](https://github.com/statsmodels/statsmodels/blob/master/statsmodels/nonparametric/_kernel_base.py#L125-L127) method is going to see `bw` is `None` and fail to set the attribute `self._bw_method`. This causes [`KDEMultivariate.__repr__`](https://github.com/statsmodels/statsmodels/blob/master/statsmodels/nonparametric/kernel_density.py#L126) to break because `self._bw_method` is not defined.

The function should read

```
    def _compute_bw(self, bw):
        """
        Computes the bandwidth of the data.

        Parameters
        ----------
        bw: array_like or str
            If array_like: user-specified bandwidth.
            If a string, should be one of:

                - cv_ml: cross validation maximum likelihood
                - normal_reference: normal reference rule of thumb
                - cv_ls: cross validation least squares

        Notes
        -----
        The default values for bw is 'normal_reference'.
        """

        self.bw_func = dict(
            normal_reference=self._normal_reference,
            cv_ml=self._cv_ml, cv_ls=self._cv_ls)

        if bw is None:
            bw = 'normal_reference'

        if not isinstance(bw, string_types):
            self._bw_method = "user-specified"
            res = np.asarray(bw)
        else:
            # The user specified a bandwidth selection method
            self._bw_method = bw
            bwfunc = self.bw_func[self._bw_method]
            res = bwfunc()

        return res
```



Discussion:
check for 0.9. This didn't have labels and got lost

Resolving patch:
diff --git a/statsmodels/nonparametric/_kernel_base.py b/statsmodels/nonparametric/_kernel_base.py
--- a/statsmodels/nonparametric/_kernel_base.py
+++ b/statsmodels/nonparametric/_kernel_base.py
@@ -123,8 +123,7 @@ def _compute_bw(self, bw):
         self.bw_func = dict(normal_reference=self._normal_reference,
                             cv_ml=self._cv_ml, cv_ls=self._cv_ls)
         if bw is None:
-            bwfunc = self.bw_func['normal_reference']
-            return bwfunc()
+            bw = 'normal_reference'
 
         if not isinstance(bw, string_types):
             self._bw_method = "user-specified"


Test patch:
diff --git a/statsmodels/nonparametric/tests/test_kernel_density.py b/statsmodels/nonparametric/tests/test_kernel_density.py
--- a/statsmodels/nonparametric/tests/test_kernel_density.py
+++ b/statsmodels/nonparametric/tests/test_kernel_density.py
@@ -1,5 +1,6 @@
 import numpy as np
 import numpy.testing as npt
+from numpy.testing import assert_allclose, assert_equal
 import pytest
 
 import statsmodels.api as sm
@@ -253,7 +254,7 @@ def test_efficient_user_specified_bw(self):
         C1 = np.random.normal(size=(nobs, ))
         C2 = np.random.normal(2, 1, size=(nobs, ))
         bw_user=[0.23, 434697.22]
-        
+
         dens = nparam.KDEMultivariate(data=[C1, C2], var_type='cc',
             bw=bw_user, defaults=nparam.EstimatorSettings(efficient=True,
                                                           randomize=False,
@@ -330,6 +331,17 @@ def test_continuous_normal_ref(self):
         # TODO: here we need a smaller tolerance.check!
         npt.assert_allclose(sm_result, R_result, atol=1e-1)
 
+        # test default bandwidth method, should be normal_reference
+        dens_nm2 = nparam.KDEMultivariateConditional(endog=[self.Italy_gdp],
+                                                    exog=[self.growth],
+                                                    dep_type='c',
+                                                    indep_type='c',
+                                                    bw=None)
+        assert_allclose(dens_nm2.bw, dens_nm.bw, rtol=1e-10)
+        assert_equal(dens_nm2._bw_method, 'normal_reference')
+        # check repr works #3125
+        repr(dens_nm2)
+
     def test_continuous_cdf(self):
         dens_nm = nparam.KDEMultivariateConditional(endog=[self.Italy_gdp],
                                                     exog=[self.growth],
@@ -380,7 +392,7 @@ def test_efficient_user_specified_bw(self):
         C1 = np.random.normal(size=(nobs, ))
         C2 = np.random.normal(2, 1, size=(nobs, ))
         bw_user=[0.23, 434697.22]
-        
+
         dens = nparam.KDEMultivariate(data=[C1, C2], var_type='cc',
             bw=bw_user, defaults=nparam.EstimatorSettings(efficient=True,
                                                           randomize=False,