Repository: statsmodels/statsmodels

Issue:
stratified contingency tables converts list of tables to 2x2 without warning
#### Describe the bug
This is about the StratifiedTable function documented here: 
https://www.statsmodels.org/stable/contingency_tables.html#stratified-2x2-tables
I was trying to implement a test of homogeneous association across two tables which were not 2x2 (I didn't properly read the function details before trying it).  For 2x2 tables, the association can be captured in a single odds ratio value, so you are testing if the tables have the same odds ratio.  What I was trying to do is an extension to tables of arbitrary size, for which you have to check if the odds ratio for any pairs of values are the same across the strata.
Anyhow, I tried to run my code, submitting a list (not an array) of two numpy tables.  The default in the initialization is to create a data cube of 2x2 via 
table = np.dstack(tables).astype(np.float64)

It turns out that this created an array of 2x2 tables for analysis, without warning me that it was fundamentally changing the shape of the data.  Actually, if you end up adding an additional element to each, so that 2x3 tables result (which should be illegal), no warning arises.  Basically the problem is that there is not a check at the beginning to make sure that the inputs are legal, and a result is returned without warning.

#### Code Sample, a copy-pastable example if possible
```python
import numpy as np
#two 6x2 (not 2x2) tables
table1 = np.array([[512, 313],[353, 207], [120, 205], [138,279],[53,138],[22,351]])
table2 = np.array([[89, 19],[17, 8], [202, 391], [131,244],[94,299],[24,317]])

#what the function returns a calculation on, which is not my goal
#I mean the table input to be a list of two tables, not a single np array
np.dstack([table1, table2])

import statsmodels.api as sm
test_of_homogeneous_association = sm.stats.StratifiedTable([table1, table2])
#my original input should have been illegal
print(test_of_homogeneous_association.test_equal_odds())

#now try adding an additional column so that inputs are 6x3

table1 = np.array([[512, 313,1],[353, 207,1], [120, 205,1], [138,279,1],[53,138,1],[22,351,1]])
table2 = np.array([[89, 19,1],[17, 8,1], [202, 391,1], [131,244,1],[94,299,1],[24,317,1]])
test_of_homogeneous_association = sm.stats.StratifiedTable([table1, table2])
#array of 2x3 tables
np.dstack([table1, table2])

```
<details>

**Note**: As you can see, there are many issues on our GitHub tracker, so it is very possible that your issue has been posted before. Please check first before submitting so that we do not have to handle and close duplicates.

**Note**: Please be sure you are using the latest released version of `statsmodels`, or a recent build of `master`. If your problem has been fixed in an unreleased version, you might be able to use `master` until a new release occurs. 

**Note**: If you are using a released version, have you verified that the bug exists in the master branch of this repository? It helps the limited resources if we know problems exist in the current master so that they do not need to check whether the code sample produces a bug in the next release.

</details>


If the issue has not been resolved, please file it in the issue tracker.

#### Expected Output
I expect there to be a warning "dimension of table is not 2x2" if not an np array

#### Output of ``import statsmodels.api as sm; sm.show_versions()``
Statsmodels
===========
Installed: 0.9.0 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\statsmodels)
Required Dependencies
=====================
cython: 0.28.2 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\Cython)
numpy: 1.16.3 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\numpy)
scipy: 1.1.0 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\scipy)
pandas: 0.25.2 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas)
    dateutil: 2.7.3 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\dateutil)
patsy: 0.5.0 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\patsy)
Optional Dependencies
=====================
matplotlib: 2.2.2 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\matplotlib)
    backend: Qt5Agg 
cvxopt: Not installed
joblib: 0.12.5 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\joblib)
Developer Tools
================
IPython: 6.4.0 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\IPython)
    jinja2: 2.10 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\jinja2)
sphinx: 1.7.4 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\sphinx)
    pygments: 2.2.0 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\pygments)
nose: 1.3.7 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages\nose)
pytest: 3.5.1 (C:\Users\samuelac\AppData\Local\Continuum\anaconda3\lib\site-packages)
virtualenv: Not installed
</details>



Discussion:

Resolving patch:
diff --git a/statsmodels/stats/contingency_tables.py b/statsmodels/stats/contingency_tables.py
--- a/statsmodels/stats/contingency_tables.py
+++ b/statsmodels/stats/contingency_tables.py
@@ -941,6 +941,10 @@ def __init__(self, tables, shift_zeros=False):
                 raise ValueError("If an ndarray, argument must be 2x2xn")
             table = tables
         else:
+            if any([np.asarray(x).shape != (2, 2) for x in tables]):
+                m = "If `tables` is a list, all of its elements should be 2x2"
+                raise ValueError(m)
+
             # Create a data cube
             table = np.dstack(tables).astype(np.float64)
 
@@ -1099,9 +1103,9 @@ def logodds_pooled_se(self):
 
         References
         ----------
-        Robins, James, Norman Breslow, and Sander Greenland. "Estimators of
-            the Mantel-Haenszel Variance Consistent in Both Sparse Data and
-            Large-Strata Limiting Models." Biometrics 42, no. 2 (1986): 311-23.
+        J. Robins, N. Breslow, S. Greenland. "Estimators of the
+        Mantel-Haenszel Variance Consistent in Both Sparse Data and
+        Large-Strata Limiting Models." Biometrics 42, no. 2 (1986): 311-23.
         """
 
         adns = np.sum(self._ad / self._n)
@@ -1205,7 +1209,8 @@ def test_equal_odds(self, adjust=False):
         c = -r * self._apb * self._apc
 
         # Expected value of first cell
-        e11 = (-b + np.sqrt(b**2 - 4*a*c)) / (2*a)
+        dr = np.sqrt(b**2 - 4*a*c)
+        e11 = (-b + dr) / (2*a)
 
         # Variance of the first cell
         v11 = (1 / e11 + 1 / (self._apc - e11) + 1 / (self._apb - e11) +


Test patch:
diff --git a/statsmodels/stats/tests/test_contingency_tables.py b/statsmodels/stats/tests/test_contingency_tables.py
--- a/statsmodels/stats/tests/test_contingency_tables.py
+++ b/statsmodels/stats/tests/test_contingency_tables.py
@@ -366,10 +366,14 @@ def test_equal_odds(self):
         if not hasattr(self, "or_homog"):
             return
 
-        rslt = self.rslt_0.test_equal_odds()
+        rslt = self.rslt.test_equal_odds(adjust=False)
         assert_allclose(rslt.statistic, self.or_homog, rtol=1e-4, atol=1e-4)
         assert_allclose(rslt.pvalue, self.or_homog_p, rtol=1e-4, atol=1e-4)
 
+        rslt = self.rslt.test_equal_odds(adjust=True)
+        assert_allclose(rslt.statistic, self.or_homog_adj, rtol=1e-4, atol=1e-4)
+        assert_allclose(rslt.pvalue, self.or_homog_adj_p, rtol=1e-4, atol=1e-4)
+
 
     def test_pandas(self):
 
@@ -428,6 +432,7 @@ def setup_class(cls):
 
 class TestStratified2(CheckStratifiedMixin):
     """
+    library(DescTools)
     data = array(c(20, 14, 10, 24,
                    15, 12, 3, 15,
                    3, 2, 3, 2,
@@ -435,6 +440,8 @@ class TestStratified2(CheckStratifiedMixin):
                    1, 0, 3, 2),
                    dim=c(2, 2, 5))
     rslt = mantelhaen.test(data)
+    bd1 = BreslowDayTest(data, correct=FALSE)
+    bd2 = BreslowDayTest(data, correct=TRUE)
     """
 
     @classmethod
@@ -457,9 +464,18 @@ def setup_class(cls):
         cls.or_lcb = 1.781135
         cls.or_ucb = 7.240633
 
+        # Breslow Day test without Tarone adjustment
+        cls.or_homog = 1.8438
+        cls.or_homog_p = 0.7645
+
+        # Breslow Day test with Tarone adjustment
+        cls.or_homog_adj = 1.8436
+        cls.or_homog_adj_p = 0.7645
+
 
 class TestStratified3(CheckStratifiedMixin):
     """
+    library(DescTools)
     data = array(c(313, 512, 19, 89,
                    207, 353, 8, 17,
                    205, 120, 391, 202,
@@ -468,6 +484,8 @@ class TestStratified3(CheckStratifiedMixin):
                    351, 22, 317, 24),
                    dim=c(2, 2, 6))
     rslt = mantelhaen.test(data)
+    bd1 = BreslowDayTest(data, correct=FALSE)
+    bd2 = BreslowDayTest(data, correct=TRUE)
     """
 
     @classmethod
@@ -491,9 +509,13 @@ def setup_class(cls):
         cls.or_lcb = 0.9402012
         cls.or_ucb = 1.2913602
 
+        # Breslow Day test without Tarone adjustment
         cls.or_homog = 18.83297
         cls.or_homog_p = 0.002064786
 
+        # Breslow Day test with Tarone adjustment
+        cls.or_homog_adj = 18.83297
+        cls.or_homog_adj_p = 0.002064786
 
 class Check2x2Mixin(object):
     @classmethod