Repository: statsmodels/statsmodels

Issue:
MixedLMResults.resid broken when vc_formula used
[example_data.txt](https://github.com/statsmodels/statsmodels/files/232593/example_data.txt)

Sample data attached. Use with the following code:

```
x = pd.io.parsers.read_csv('example_data.txt') 
m = smf.MixedLM.from_formula('sf~area*phase*stream', data=x, groups=x['cell'],
                             vc_formula={'target': '0+target'})
fit = m.fit()
fit.resid
```

Traceback:

```
/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/base/wrapper.py in __getattribute__(self, attr)
     33             pass
     34 
---> 35         obj = getattr(results, attr)
     36         data = results.model.data
     37         how = self._wrap_attrs.get(attr)

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/tools/decorators.py in __get__(self, obj, type)
     95         if _cachedval is None:
     96             # Call the "fget" function
---> 97             _cachedval = self.fget(obj)
     98             # Set the attribute in obj
     99             # print("Setting %s in cache to %s" % (name, _cachedval))

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/regression/mixed_linear_model.py in resid(self)
   2132         fixed effects and the predicted random effects.
   2133         """
-> 2134         return self.model.endog - self.fittedvalues
   2135 
   2136 

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/tools/decorators.py in __get__(self, obj, type)
     95         if _cachedval is None:
     96             # Call the "fget" function
---> 97             _cachedval = self.fget(obj)
     98             # Set the attribute in obj
     99             # print("Setting %s in cache to %s" % (name, _cachedval))

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/regression/mixed_linear_model.py in fittedvalues(self)
   2113             ix = self.model.row_indices[group]
   2114 
-> 2115             mat = [self.model.exog_re_li[group_ix]]
   2116             for c in self.model._vc_names:
   2117                 if group in self.model.exog_vc[c]:

TypeError: 'NoneType' object is not subscriptable

---> 97             _cachedval = self.fget(obj)
     98             # Set the attribute in obj
     99             # print("Setting %s in cache to %s" % (name, _cachedval))

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/regression/mixed_linear_model.py in fittedvalues(self)
   2113             ix = self.model.row_indices[group]
   2114 
-> 2115             mat = [self.model.exog_re_li[group_ix]]
   2116             for c in self.model._vc_names:
   2117                 if group in self.model.exog_vc[c]:
```

TypeError: 'NoneType' object is not subscriptable

MixedLMResults.resid broken when vc_formula used
[example_data.txt](https://github.com/statsmodels/statsmodels/files/232593/example_data.txt)

Sample data attached. Use with the following code:

```
x = pd.io.parsers.read_csv('example_data.txt') 
m = smf.MixedLM.from_formula('sf~area*phase*stream', data=x, groups=x['cell'],
                             vc_formula={'target': '0+target'})
fit = m.fit()
fit.resid
```

Traceback:

```
/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/base/wrapper.py in __getattribute__(self, attr)
     33             pass
     34 
---> 35         obj = getattr(results, attr)
     36         data = results.model.data
     37         how = self._wrap_attrs.get(attr)

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/tools/decorators.py in __get__(self, obj, type)
     95         if _cachedval is None:
     96             # Call the "fget" function
---> 97             _cachedval = self.fget(obj)
     98             # Set the attribute in obj
     99             # print("Setting %s in cache to %s" % (name, _cachedval))

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/regression/mixed_linear_model.py in resid(self)
   2132         fixed effects and the predicted random effects.
   2133         """
-> 2134         return self.model.endog - self.fittedvalues
   2135 
   2136 

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/tools/decorators.py in __get__(self, obj, type)
     95         if _cachedval is None:
     96             # Call the "fget" function
---> 97             _cachedval = self.fget(obj)
     98             # Set the attribute in obj
     99             # print("Setting %s in cache to %s" % (name, _cachedval))

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/regression/mixed_linear_model.py in fittedvalues(self)
   2113             ix = self.model.row_indices[group]
   2114 
-> 2115             mat = [self.model.exog_re_li[group_ix]]
   2116             for c in self.model._vc_names:
   2117                 if group in self.model.exog_vc[c]:

TypeError: 'NoneType' object is not subscriptable

---> 97             _cachedval = self.fget(obj)
     98             # Set the attribute in obj
     99             # print("Setting %s in cache to %s" % (name, _cachedval))

/home/bburan/bin/anaconda3/envs/notebook/lib/python3.5/site-packages/statsmodels/regression/mixed_linear_model.py in fittedvalues(self)
   2113             ix = self.model.row_indices[group]
   2114 
-> 2115             mat = [self.model.exog_re_li[group_ix]]
   2116             for c in self.model._vc_names:
   2117                 if group in self.model.exog_vc[c]:
```

TypeError: 'NoneType' object is not subscriptable



Discussion:

Resolving patch:
diff --git a/statsmodels/regression/mixed_linear_model.py b/statsmodels/regression/mixed_linear_model.py
--- a/statsmodels/regression/mixed_linear_model.py
+++ b/statsmodels/regression/mixed_linear_model.py
@@ -2112,7 +2112,9 @@ def fittedvalues(self):
         for group_ix, group in enumerate(self.model.group_labels):
             ix = self.model.row_indices[group]
 
-            mat = [self.model.exog_re_li[group_ix]]
+            mat = []
+            if self.model.exog_re_li is not None:
+                mat.append(self.model.exog_re_li[group_ix])
             for c in self.model._vc_names:
                 if group in self.model.exog_vc[c]:
                     mat.append(self.model.exog_vc[c][group])


Test patch:
diff --git a/statsmodels/regression/tests/test_lme.py b/statsmodels/regression/tests/test_lme.py
--- a/statsmodels/regression/tests/test_lme.py
+++ b/statsmodels/regression/tests/test_lme.py
@@ -255,6 +255,7 @@ def test_vcomp_1(self):
         assert_allclose(result1.bse[[0, 1, 3]],
                         result2.bse, atol=1e-2, rtol=1e-2)
 
+
     def test_vcomp_2(self):
         """
         Simulated data comparison to R
@@ -317,6 +318,28 @@ def test_vcomp_2(self):
         assert_allclose(result1.bse.iloc[0:3], [
                         0.12610, 0.03938, 0.03848], rtol=1e-3)
 
+    def test_vcomp_3(self):
+        """
+        Test a model with vcomp but no other random effects, using formulas.
+        """
+
+        np.random.seed(4279)
+        x1 = np.random.normal(size=400)
+        groups = np.kron(np.arange(100), np.ones(4))
+        slopes = np.random.normal(size=100)
+        slopes = np.kron(slopes, np.ones(4)) * x1
+        y = slopes + np.random.normal(size=400)
+        vc_fml = {"a": "0 + x1"}
+        df = pd.DataFrame({"y": y, "x1": x1, "groups": groups})
+
+        model = MixedLM.from_formula("y ~ 1", groups="groups", vc_formula=vc_fml, data=df)
+        result = model.fit()
+        result.summary()
+
+        assert_allclose(result.resid.iloc[0:4], np.r_[-1.180753, 0.279966, 0.578576, -0.667916], rtol=1e-3)
+        assert_allclose(result.fittedvalues.iloc[0:4], np.r_[-0.101549, 0.028613, -0.224621, -0.126295], rtol=1e-3)
+
+
     def test_sparse(self):
 
         import scipy