Repository: statsmodels/statsmodels

Issue:
discreteResults margeff method not tests, obsolete
the margeff method has zero test coverage, get_margeff is the new method

is margeff obsolete ?
or does it need unit tests comparing to separated out Margins class ?



Discussion:
@jseabold  Why do we deprecate a broken function ?

for example Logit case here  (there is PR #892 for fixing the examples)
http://statsmodels.sourceforge.net/devel/examples/notebooks/generated/example_discrete.html

```
logit_mod = sm.Logit(spector_data.endog, spector_data.exog)
logit_res = logit_mod.fit()
print 'Parameters: ', logit_res.params
print 'Marginal effects: ', logit_res.margeff()

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-761e1b345c46> in <module>()
      2 logit_res = logit_mod.fit()
      3 print 'Parameters: ', logit_res.params
----> 4 print 'Marginal effects: ', logit_res.margeff()

e:\josef\eclipsegworkspace\statsmodels-git\statsmodels-all-new2\statsmodels\statsmodels\discrete\discrete_model.pyc in margeff(self, at, method, atexog, dummy, count)
   2111                                                 self.model._derivative_exog,
   2112                                                 dummy_ind, count_ind,
-> 2113                                                 method)
   2114         # don't care about at constant
   2115         self.margeff_cov = margeff_cov[ind][:, ind]

TypeError: margeff_cov_with_se() takes exactly 10 arguments (9 given)

Optimization terminated successfully.
         Current function value: 0.402801
         Iterations 7
Parameters:  [  2.82611259   0.09515766   2.37868766 -13.02134686]
Marginal effects: 

e:\josef\eclipsegworkspace\statsmodels-git\statsmodels-all-new2\statsmodels\statsmodels\discrete\discrete_model.py:2043: FutureWarning: This method is deprecated and will be removed in 0.6.0. Use get_margeff instead
  " Use get_margeff instead", FutureWarning)
```

I don't think that case worked before either, and I didn't feel like fixing it since it's deprecated. I deprecated it because I had demo'd it in a few talks. I'm fine with removing it though. Or just raising a NotImplementedError to use get_margeff or something. 

I think removing it would be best in that case. I think it's strange to get a deprecation warning for something that doesn't and didn't work. If it didn't work before, then there should not be any code depending on it.

One possibility would be to delegate to the new class, if we want to keep the deprecation warning.


Resolving patch:
diff --git a/statsmodels/discrete/discrete_model.py b/statsmodels/discrete/discrete_model.py
--- a/statsmodels/discrete/discrete_model.py
+++ b/statsmodels/discrete/discrete_model.py
@@ -2185,152 +2185,10 @@ def get_margeff(self, at='overall', method='dydx', atexog=None,
 
     def margeff(self, at='overall', method='dydx', atexog=None, dummy=False,
             count=False):
-        """Get marginal effects of the fitted model.
-
-        Parameters
-        ----------
-        at : str, optional
-            Options are:
-
-            - 'overall', The average of the marginal effects at each
-              observation.
-            - 'mean', The marginal effects at the mean of each regressor.
-            - 'median', The marginal effects at the median of each regressor.
-            - 'zero', The marginal effects at zero for each regressor.
-            - 'all', The marginal effects at each observation.
-
-            Note that if `exog` is specified, then marginal effects for all
-            variables not specified by `exog` are calculated using the `at`
-            option.
-        method : str, optional
-            Options are:
-
-            - 'dydx' - dy/dx - No transformation is made and marginal effects
-              are returned.  This is the default.
-            - 'eyex' - estimate elasticities of variables in `exog` --
-              d(lny)/d(lnx)
-            - 'dyex' - estimate semielasticity -- dy/d(lnx)
-            - 'eydx' - estimate semeilasticity -- d(lny)/dx
-
-            Note that tranformations are done after each observation is
-            calculated.  Semi-elasticities for binary variables are computed
-            using the midpoint method. 'dyex' and 'eyex' do not make sense
-            for discrete variables.
-        atexog : array-like, optional
-            Optionally, you can provide the exogenous variables over which to
-            get the marginal effects.  This should be a dictionary with the key
-            as the zero-indexed column number and the value of the dictionary.
-            Default is None for all independent variables less the constant.
-        dummy : bool, optional
-            If False, treats binary variables (if present) as continuous.  This
-            is the default.  Else if True, treats binary variables as
-            changing from 0 to 1.  Note that any variable that is either 0 or 1
-            is treated as binary.  Each binary variable is treated separately
-            for now.
-        count : bool, optional
-            If False, treats count variables (if present) as continuous.  This
-            is the default.  Else if True, the marginal effect is the
-            change in probabilities when each observation is increased by one.
-
-        Returns
-        -------
-        effects : ndarray
-            the marginal effect corresponding to the input options
-
-        Notes
-        -----
-        When using after Poisson, returns the expected number of events
-        per period, assuming that the model is loglinear.
-        """
-        #TODO:
-        #factor : None or dictionary, optional
-        #    If a factor variable is present (it must be an integer, though
-        #    of type float), then `factor` may be a dict with the zero-indexed
-        #    column of the factor and the value should be the base-outcome.
-
-        from statsmodels.discrete.discrete_margins import (_check_margeff_args,
-                        _check_discrete_args, _isdummy, _iscount,
-                        _get_margeff_exog, _get_count_effects,
-                        _get_dummy_effects, _effects_at)
-
         import warnings
         warnings.warn("This method is deprecated and will be removed in 0.6.0."
                 " Use get_margeff instead", FutureWarning)
-        from statsmodels.discrete.discrete_margins import margeff_cov_with_se
-
-        # get local variables
-        model = self.model
-        params = self.params
-        method = method.lower()
-        at = at.lower()
-        exog = model.exog.copy() # copy because values are changed
-        ind = exog.var(0) != 0 # index for non-constants
-
-        _check_margeff_args(at, method)
-
-        if np.any(~ind):
-            const_idx = np.where(~ind)[0]
-        else:
-            const_idx = None
-
-        # handle discrete exogenous variables
-        if dummy:
-            _check_discrete_args(at, method)
-            dummy_ind = _isdummy(exog)
-            exog_ind = dummy_ind.copy()
-            # adjust back for a constant because effects doesn't have one
-            if const_idx is not None:
-                dummy_ind[dummy_ind > const_idx] -= 1
-            if dummy_ind.size == 0: # don't waste your time
-                dummy = False
-                dummy_ind = None # this gets passed to stand err func
-            else:
-                dummy_ind = zip(dummy_ind, exog_ind[:])
-        else:
-            dummy_ind = None
-
-        if count:
-            _check_discrete_args(at, method)
-            count_ind = _iscount(exog)
-            exog_ind = count_ind.copy()
-            # adjust back for a constant because effects doesn't have one
-            if const_idx is not None:
-                count_ind[count_ind > const_idx] -= 1
-            if count_ind.size == 0: # don't waste your time
-                count = False
-                count_ind = None # for stand err func
-            else:
-                count_ind = zip(count_ind, exog_ind)
-        else:
-            count_ind = None
-
-        # get the exogenous variables
-        exog = _get_margeff_exog(exog, at, atexog, ind)
-
-        # get base marginal effects, handled by sub-classes
-        effects = model._derivative_exog(params, exog, method)
-
-        effects = _effects_at(effects, at)
-
-        if dummy:
-            effects = _get_dummy_effects(effects, exog, dummy_ind, method,
-                                         model, params)
-
-        if count:
-            effects = _get_count_effects(effects, exog, count_ind, method,
-                                         model, params)
-
-        # Set standard error of the marginal effects by Delta method.
-        margeff_cov, margeff_se = margeff_cov_with_se(model, params, exog,
-                                                self.cov_params(), at,
-                                                self.model._derivative_exog,
-                                                dummy_ind, count_ind,
-                                                method)
-        # don't care about at constant
-        self.margeff_cov = margeff_cov[ind][:, ind]
-        self.margeff_se = margeff_se[ind]
-        self.margfx = effects
-        return effects
+        return self.get_margeff(at, method, atexog, dummy, count)
 
 
     def summary(self, yname=None, xname=None, title=None, alpha=.05,


Test patch: