Repository: pandas-dev/pandas

Issue:
BUG: resample with datetime64 data on series looses dtype
From SO: http://stackoverflow.com/questions/37106810/bug-in-python-pandas-pandas-series-resample-vs-pandas-dataframe-resample

```
In [7]: import datetime as dt

In [8]: df = pd.DataFrame([[dt.datetime(2016,1,31,15)], [dt.datetime(2016,2,7,17)]], index=[dt.datetime(2016,1,31,15), dt.datetime(2016,2,7,17)], columns=['timestamp'])

In [10]: df
Out[10]:
                              timestamp
2016-01-31 15:00:00 2016-01-31 15:00:00
2016-02-07 17:00:00 2016-02-07 17:00:00

In [11]: df.resample('D').first().timestamp
Out[11]:
2016-01-31   2016-01-31 15:00:00
2016-02-01                   NaT
2016-02-02                   NaT
2016-02-03                   NaT
2016-02-04                   NaT
2016-02-05                   NaT
2016-02-06                   NaT
2016-02-07   2016-02-07 17:00:00
Freq: D, Name: timestamp, dtype: datetime64[ns]

In [12]: df.timestamp.resample('D').first()
Out[12]:
2016-01-31    1.454252e+18
2016-02-01             NaN
2016-02-02             NaN
2016-02-03             NaN
2016-02-04             NaN
2016-02-05             NaN
2016-02-06             NaN
2016-02-07    1.454864e+18
Freq: D, Name: timestamp, dtype: float64

```

Tested it with latest master



Discussion:
related to #3087 (though that's pretty old).

This is still broken with Timedeltas
Gonna add some tests, and try real quick for a fix.
(gonna ignore the incorrect bins for now?)
repro:

```
In [21]: df = DataFrame({'time':timedelta_range('1 day', '4 day', freq='D')},
                index=timedelta_range('1 day', '4 day', freq='D'))

In [22]: df
Out[22]: 
         time
1 days 1 days
2 days 2 days
3 days 3 days
4 days 4 days

In [23]: df.resample('2D').first()
Out[23]: 
         time
1 days 1 days
3 days 3 days
5 days    NaT

In [24]: df.time.resample('2D').first()
Out[24]: 
1 days    8.640000e+13
3 days    2.592000e+14
5 days             NaN
Freq: 2D, Name: time, dtype: float64
```

output of pd.show_versions

```
INSTALLED VERSIONS
------------------
commit: 6645b2b11a82343e5f07b15a25a250f411067819
python: 3.5.2.final.0
python-bits: 64
OS: Linux
OS-release: 4.4.0-21-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8

pandas: 0.18.1+391.g6645b2b.dirty
nose: 1.3.7
pip: 8.1.2
setuptools: 23.0.0
Cython: 0.24
numpy: 1.11.1
scipy: 0.17.1
statsmodels: 0.6.1
xarray: None
IPython: 4.2.0
sphinx: 1.4.1
patsy: 0.4.1
dateutil: 2.5.3
pytz: 2016.4
blosc: None
bottleneck: 1.1.0
tables: 3.2.2
numexpr: 2.6.0
matplotlib: 1.5.1
openpyxl: 2.3.2
xlrd: 1.0.0
xlwt: 1.1.2
xlsxwriter: 0.9.2
lxml: 3.6.0
bs4: 4.4.1
html5lib: None
httplib2: None
apiclient: None
sqlalchemy: 1.0.13
pymysql: None
psycopg2: None
jinja2: 2.8
boto: 2.40.0
pandas_datareader: None
```


Resolving patch:
diff --git a/pandas/types/cast.py b/pandas/types/cast.py
--- a/pandas/types/cast.py
+++ b/pandas/types/cast.py
@@ -12,7 +12,7 @@
                      is_timedelta64_dtype, is_dtype_equal,
                      is_float_dtype, is_complex_dtype,
                      is_integer_dtype, is_datetime_or_timedelta_dtype,
-                     is_scalar,
+                     is_bool_dtype, is_scalar,
                      _string_dtypes,
                      _coerce_to_dtype,
                      _ensure_int8, _ensure_int16,
@@ -89,7 +89,7 @@ def trans(x):  # noqa
 
         if issubclass(dtype.type, np.floating):
             return result.astype(dtype)
-        elif dtype == np.bool_ or issubclass(dtype.type, np.integer):
+        elif is_bool_dtype(dtype) or is_integer_dtype(dtype):
 
             # if we don't have any elements, just astype it
             if not np.prod(result.shape):


Test patch:
diff --git a/pandas/tests/types/test_cast.py b/pandas/tests/types/test_cast.py
--- a/pandas/tests/types/test_cast.py
+++ b/pandas/tests/types/test_cast.py
@@ -24,44 +24,56 @@
 _multiprocess_can_split_ = True
 
 
-def test_downcast_conv():
-    # test downcasting
+class TestPossiblyDowncast(tm.TestCase):
 
-    arr = np.array([8.5, 8.6, 8.7, 8.8, 8.9999999999995])
-    result = _possibly_downcast_to_dtype(arr, 'infer')
-    assert (np.array_equal(result, arr))
+    def test_downcast_conv(self):
+        # test downcasting
 
-    arr = np.array([8., 8., 8., 8., 8.9999999999995])
-    result = _possibly_downcast_to_dtype(arr, 'infer')
-    expected = np.array([8, 8, 8, 8, 9])
-    assert (np.array_equal(result, expected))
-
-    arr = np.array([8., 8., 8., 8., 9.0000000000005])
-    result = _possibly_downcast_to_dtype(arr, 'infer')
-    expected = np.array([8, 8, 8, 8, 9])
-    assert (np.array_equal(result, expected))
-
-    # conversions
+        arr = np.array([8.5, 8.6, 8.7, 8.8, 8.9999999999995])
+        result = _possibly_downcast_to_dtype(arr, 'infer')
+        assert (np.array_equal(result, arr))
 
-    expected = np.array([1, 2])
-    for dtype in [np.float64, object, np.int64]:
-        arr = np.array([1.0, 2.0], dtype=dtype)
+        arr = np.array([8., 8., 8., 8., 8.9999999999995])
         result = _possibly_downcast_to_dtype(arr, 'infer')
-        tm.assert_almost_equal(result, expected, check_dtype=False)
+        expected = np.array([8, 8, 8, 8, 9])
+        assert (np.array_equal(result, expected))
 
-    for dtype in [np.float64, object]:
-        expected = np.array([1.0, 2.0, np.nan], dtype=dtype)
-        arr = np.array([1.0, 2.0, np.nan], dtype=dtype)
+        arr = np.array([8., 8., 8., 8., 9.0000000000005])
         result = _possibly_downcast_to_dtype(arr, 'infer')
-        tm.assert_almost_equal(result, expected)
-
-    # empties
-    for dtype in [np.int32, np.float64, np.float32, np.bool_,
-                  np.int64, object]:
-        arr = np.array([], dtype=dtype)
-        result = _possibly_downcast_to_dtype(arr, 'int64')
-        tm.assert_almost_equal(result, np.array([], dtype=np.int64))
-        assert result.dtype == np.int64
+        expected = np.array([8, 8, 8, 8, 9])
+        assert (np.array_equal(result, expected))
+
+        # conversions
+
+        expected = np.array([1, 2])
+        for dtype in [np.float64, object, np.int64]:
+            arr = np.array([1.0, 2.0], dtype=dtype)
+            result = _possibly_downcast_to_dtype(arr, 'infer')
+            tm.assert_almost_equal(result, expected, check_dtype=False)
+
+        for dtype in [np.float64, object]:
+            expected = np.array([1.0, 2.0, np.nan], dtype=dtype)
+            arr = np.array([1.0, 2.0, np.nan], dtype=dtype)
+            result = _possibly_downcast_to_dtype(arr, 'infer')
+            tm.assert_almost_equal(result, expected)
+
+        # empties
+        for dtype in [np.int32, np.float64, np.float32, np.bool_,
+                      np.int64, object]:
+            arr = np.array([], dtype=dtype)
+            result = _possibly_downcast_to_dtype(arr, 'int64')
+            tm.assert_almost_equal(result, np.array([], dtype=np.int64))
+            assert result.dtype == np.int64
+
+    def test_datetimelikes_nan(self):
+        arr = np.array([1, 2, np.nan])
+        exp = np.array([1, 2, np.datetime64('NaT')], dtype='datetime64[ns]')
+        res = _possibly_downcast_to_dtype(arr, 'datetime64[ns]')
+        tm.assert_numpy_array_equal(res, exp)
+
+        exp = np.array([1, 2, np.timedelta64('NaT')], dtype='timedelta64[ns]')
+        res = _possibly_downcast_to_dtype(arr, 'timedelta64[ns]')
+        tm.assert_numpy_array_equal(res, exp)
 
 
 class TestInferDtype(tm.TestCase):
diff --git a/pandas/tseries/tests/test_resample.py b/pandas/tseries/tests/test_resample.py
--- a/pandas/tseries/tests/test_resample.py
+++ b/pandas/tseries/tests/test_resample.py
@@ -1935,6 +1935,23 @@ def test_resample_with_nat(self):
 
         assert_frame_equal(frame.resample('60s').mean(), frame_3s)
 
+    def test_resample_timedelta_values(self):
+        # GH 13119
+        # check that timedelta dtype is preserved when NaT values are
+        # introduced by the resampling
+
+        times = timedelta_range('1 day', '4 day', freq='4D')
+        df = DataFrame({'time': times}, index=times)
+
+        times2 = timedelta_range('1 day', '4 day', freq='2D')
+        exp = Series(times2, index=times2, name='time')
+        exp.iloc[1] = pd.NaT
+
+        res = df.resample('2D').first()['time']
+        tm.assert_series_equal(res, exp)
+        res = df['time'].resample('2D').first()
+        tm.assert_series_equal(res, exp)
+
 
 class TestPeriodIndex(Base, tm.TestCase):
     _multiprocess_can_split_ = True