Repository: statsmodels/statsmodels

Issue:
BUG: fix error in Poisson when offset or exposure is a pd.Series
- [X] closes #7015
- [X] tests added / passed. 
- [X] code/documentation is well formatted.  
- [X] properly formatted commit message. See 
      [NumPy's guide](https://docs.scipy.org/doc/numpy-1.15.1/dev/gitwash/development_workflow.html#writing-the-commit-message). 

<details>
Just do np.asarray in the __init__ method of CountModel. Added a test that fails on master but passes here

**Notes**:

* It is essential that you add a test when making code changes. Tests are not 
  needed for doc changes.
* When adding a new function, test values should usually be verified in another package (e.g., R/SAS/Stata).
* When fixing a bug, you must add a test that would produce the bug in master and
  then show that it is fixed with the new code.
* New code additions must be well formatted. Changes should pass flake8. If on Linux or OSX, you can
  verify you changes are well formatted by running 
  ```
  git diff upstream/master -u -- "*.py" | flake8 --diff --isolated
  ```
  assuming `flake8` is installed. This command is also available on Windows 
  using the Windows System for Linux once `flake8` is installed in the 
  local Linux environment. While passing this test is not required, it is good practice and it help 
  improve code quality in `statsmodels`.
* Docstring additions must render correctly, including escapes and LaTeX.

</details>



Discussion:

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
@@ -774,7 +774,10 @@ def __init__(self, endog, exog, offset=None, exposure=None, missing='none',
         super().__init__(endog, exog, check_rank, missing=missing,
                          offset=offset, exposure=exposure, **kwargs)
         if exposure is not None:
+            self.exposure = np.asarray(self.exposure)
             self.exposure = np.log(self.exposure)
+        if offset is not None:
+            self.offset = np.asarray(self.offset)
         self._check_inputs(self.offset, self.exposure, self.endog)
         if offset is None:
             delattr(self, 'offset')


Test patch:
diff --git a/statsmodels/discrete/tests/test_count_model.py b/statsmodels/discrete/tests/test_count_model.py
--- a/statsmodels/discrete/tests/test_count_model.py
+++ b/statsmodels/discrete/tests/test_count_model.py
@@ -4,6 +4,7 @@
 from numpy.testing import (assert_,
                            assert_equal, assert_array_equal, assert_allclose)
 import pytest
+import pandas as pd
 
 import statsmodels.api as sm
 from .results.results_discrete import RandHIE
@@ -67,7 +68,6 @@ def test_summary(self):
         # GH 4581
         assert 'Covariance Type:' in str(summ)
 
-
 class TestZeroInflatedModel_logit(CheckGeneric):
     @classmethod
     def setup_class(cls):
@@ -643,3 +643,19 @@ def test_zero_nonzero_mean(self):
         mean2 = ((1 - self.res.predict(which='prob-zero').mean()) *
                  self.res.predict(which='mean-nonzero').mean())
         assert_allclose(mean1, mean2, atol=0.2)
+
+
+class TestPandasOffset:
+
+    def test_pd_offset_exposure(self):
+        endog = pd.DataFrame({'F': [0.0, 0.0, 0.0, 0.0, 1.0]})
+        exog = pd.DataFrame({'I': [1.0, 1.0, 1.0, 1.0, 1.0],
+                             'C': [0.0, 1.0, 0.0, 1.0, 0.0]})
+        exposure = pd.Series([1., 1, 1, 2, 1])
+        offset = pd.Series([1, 1, 1, 2, 1])
+        sm.Poisson(endog=endog, exog=exog, offset=offset).fit()
+        inflations = ['logit', 'probit']
+        for inflation in inflations:
+            sm.ZeroInflatedPoisson(endog=endog, exog=exog["I"],
+                                   exposure=exposure,
+                                   inflation=inflation).fit()