Repository: statsmodels/statsmodels

Issue:
summry() should check the number of names provided in xname argument
Hi,

It seems currently the `summary()` method does not check if the number of variable names provided with `xname` argument is smaller than the number of variables included in an analysis (I only used this with OLS so far). 

The issue is that if I supply 9 variable names by mistake when in fact I have 10 variables, `summary()` only prints out those 9 variables and truncate the last one. This is prone to happen when I have a dataset without the intercept and I keep the variable names in a list separately. I just pass the dataset knowing that OLS will automatically include the intercept (I'm using a formula). Since it is easy to forget to add `Intercept` to the list for the `xname` argument when I call `summary()`, if I do that, when I see the results it does not make any sense since the first variable's estimates are actually for the intercept.

Hence, I think it would be great if I have `K` number of variables (including the intercept) and pass `K-1` number of names for `xname` argument, `summary()` automatically adds `Intercept` to the list of the names. I think making it do that only if the user originally did not include the intercept in the data would make sense. If I provide less than `K-1` number of names then it should raise an exception. 

If this gets too complicated, I think at least `summary` should print out the variables without `xnames` (the `K`'th variable in the above example) with generic names. Then the user should be able to figure out something is not right by looking at the results output. 



Discussion:
issue did not have label and got lost.
I find this behavior annoying, but usually it is because of a but. I'm not sure whether we should raise or fill with made-up names. However, I think we should not assume that a name with a meaning like intercept is appropriate.
I think this should not happen unless there is a bug in the name handling, which would argue in favor of raising an exception. 
Thanks for the reply! I even forgot about this issue. Yes I agree - I think it should simply raise an exception instead of trying to guess what user might have wanted to do.

Resolving patch:
diff --git a/statsmodels/iolib/summary.py b/statsmodels/iolib/summary.py
--- a/statsmodels/iolib/summary.py
+++ b/statsmodels/iolib/summary.py
@@ -110,6 +110,12 @@ def summary(self, yname=None, xname=None, title=0, alpha=.05,
     if title == 0:
         title = _model_types[self.model.__class__.__name__]
 
+    if xname is not None and len(xname) != len(self.params):
+        # GH 2298
+        raise ValueError('User supplied xnames must have the same number of '
+                         'entries as the number of model parameters '
+                         '({0})'.format(len(self.params)))
+
     yname, xname = _getnames(self, yname, xname)
 
     time_now = time.localtime()


Test patch:
diff --git a/statsmodels/iolib/tests/test_summary.py b/statsmodels/iolib/tests/test_summary.py
--- a/statsmodels/iolib/tests/test_summary.py
+++ b/statsmodels/iolib/tests/test_summary.py
@@ -5,6 +5,7 @@
 from __future__ import print_function
 
 import numpy as np  # noqa: F401
+import pytest
 
 from statsmodels.datasets import macrodata
 from statsmodels.regression.linear_model import OLS
@@ -21,6 +22,16 @@ def test_escaped_variable_name():
     assert 'CPI_' in res.summary().as_text()
 
 
+def test_wrong_len_xname(reset_randomstate):
+    y = np.random.randn(100)
+    x = np.random.randn(100, 2)
+    res = OLS(y, x).fit()
+    with pytest.raises(ValueError):
+        res.summary(xname=['x1'])
+    with pytest.raises(ValueError):
+        res.summary(xname=['x1', 'x2', 'x3'])
+
+
 if __name__ == '__main__':
 
     from statsmodels.regression.tests.test_regression import TestOLS