Repository: statsmodels/statsmodels

Issue:
Error fitting kde.KDEUnivariate using integer arrays
Version info:

```
python version:
2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2]
statsmodels version:
0.5.0
git revision:
82e027e91cac47cfcfbcab754a244731cd726f06
installation method:
pip install --user statsmodels
```

Running the following snippet:

``` python
import numpy
from statsmodels.nonparametric import kde

rand_ints = numpy.random.random_integers(0, 100, size=100)
rand_floats = numpy.random.random_sample(size=100)

# OK
kde_ = kde.KDEUnivariate(rand_floats)
kde_.fit()

# Crash
kde_ = kde.KDEUnivariate(rand_ints)
kde_.fit()
```

produces the following error:

```
Traceback (most recent call last):
  File "./statsmodels_01.py", line 40, in <module>
    kde_.fit()
  File "/home/kian/.local/lib/python2.7/site-packages/statsmodels/nonparametric/kde.py", line 142, in fit
    clip=clip, cut=cut)
  File "/home/kian/.local/lib/python2.7/site-packages/statsmodels/nonparametric/kde.py", line 484, in kdensityfft
    binned = fast_linbin(X,a,b,gridsize)/(delta*nobs)
  File "linbin.pyx", line 17, in statsmodels.nonparametric.linbin.fast_linbin (statsmodels/nonparametric/linbin.c:1246)
ValueError: Buffer dtype mismatch, expected 'DOUBLE' but got 'long'
```

I can avoid this error by casting integer input values (to `kde.KDEUnivariate`) to numpy floats:

``` python
# FIX: cast integer values to floats.
# OK
kde_ = kde.KDEUnivariate(rand_ints.astype(numpy.float))
kde_.fit()
```

Similar issues were raised:
- #1586
- https://github.com/scikit-learn/scikit-learn/issues/1709

Thanks!



Discussion:
@kianho Thanks for reporting

another dtype issue, we are currently not checking that the dtype of the user makes sense.
We have several open issues, and we need to change to enforcing dtypes soon.
A more serious issue in this case is that we only support float (?) in the cython/c code anyway.

For now it's up to the user to ensure that the dtype makes sense. Best is to always cast to float, since we would have to convert anyway.


Resolving patch:
diff --git a/statsmodels/nonparametric/kde.py b/statsmodels/nonparametric/kde.py
--- a/statsmodels/nonparametric/kde.py
+++ b/statsmodels/nonparametric/kde.py
@@ -15,6 +15,7 @@
 from scipy import integrate, stats
 from statsmodels.sandbox.nonparametric import kernels
 from statsmodels.tools.decorators import cache_readonly
+from statsmodels.tools.validation import array_like
 from . import bandwidths
 from .kdetools import (forrt, revrt, silverman_transform)
 from .linbin import fast_linbin
@@ -75,7 +76,7 @@ class KDEUnivariate(object):
     """
 
     def __init__(self, endog):
-        self.endog = np.asarray(endog)
+        self.endog = array_like(endog, "endog", ndim=1, contiguous=True)
 
     def fit(self, kernel="gau", bw="normal_reference", fft=True, weights=None,
             gridsize=None, adjust=1, cut=3, clip=(-np.inf, np.inf)):
diff --git a/statsmodels/sandbox/nonparametric/kde2.py b/statsmodels/sandbox/nonparametric/kde2.py
--- a/statsmodels/sandbox/nonparametric/kde2.py
+++ b/statsmodels/sandbox/nonparametric/kde2.py
@@ -1,6 +1,9 @@
 # -*- coding: utf-8 -*-
 from statsmodels.compat.python import lzip
+
 import numpy as np
+
+from statsmodels.tools.validation import array_like
 from . import kernels
 
 
@@ -19,7 +22,7 @@ class KDE(object):
     """
     #TODO: amend docs for Nd case?
     def __init__(self, x, kernel=None):
-        x = np.asarray(x)
+        x = array_like(x, "x", maxdim=2, contiguous=True)
         if x.ndim == 1:
             x = x[:,None]
 


Test patch:
diff --git a/statsmodels/nonparametric/tests/test_kernel_density.py b/statsmodels/nonparametric/tests/test_kernel_density.py
--- a/statsmodels/nonparametric/tests/test_kernel_density.py
+++ b/statsmodels/nonparametric/tests/test_kernel_density.py
@@ -120,6 +120,16 @@ def test_all_samples_same_location_bw(self):
         with pytest.raises(RuntimeError, match="Selected KDE bandwidth is 0"):
             kde.fit()
 
+    def test_int(self, reset_randomstate):
+        x = np.random.randint(0, 100, size=1000)
+        kde = nparam.KDEUnivariate(x)
+        kde.fit()
+
+        kde_double = nparam.KDEUnivariate(x.astype("double"))
+        kde_double.fit()
+
+        assert_allclose(kde.bw, kde_double.bw)
+
 
 class TestKDEMultivariate(KDETestBase):
     @pytest.mark.slow