Skip to content

Commit b7dc475

Browse files
committed
Merge pull request #6588 from jreback/date_fill
BUG: Bug in fillna with method = bfill/ffill and datetime64[ns] dtype (GH6587)
2 parents 391ed32 + bf569f9 commit b7dc475

File tree

4 files changed

+42
-24
lines changed

4 files changed

+42
-24
lines changed

doc/source/release.rst

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ Bug Fixes
225225
- Bug in indexing: empty list lookup caused ``IndexError`` exceptions (:issue:`6536`, :issue:`6551`)
226226
- Series.quantile raising on an ``object`` dtype (:issue:`6555`)
227227
- Bug in ``.xs`` with a ``nan`` in level when dropped (:issue:`6574`)
228+
- Bug in fillna with method = 'bfill/ffill' and ``datetime64[ns]`` dtype (:issue:`6587`)
228229

229230
pandas 0.13.1
230231
-------------

pandas/core/common.py

+27-23
Original file line numberDiff line numberDiff line change
@@ -1244,13 +1244,14 @@ def wrapper(arr, mask, limit=None):
12441244
np.int64)
12451245

12461246

1247-
def pad_1d(values, limit=None, mask=None):
1247+
def pad_1d(values, limit=None, mask=None, dtype=None):
12481248

1249-
dtype = values.dtype.name
1249+
if dtype is None:
1250+
dtype = values.dtype
12501251
_method = None
12511252
if is_float_dtype(values):
1252-
_method = getattr(algos, 'pad_inplace_%s' % dtype, None)
1253-
elif is_datetime64_dtype(values):
1253+
_method = getattr(algos, 'pad_inplace_%s' % dtype.name, None)
1254+
elif dtype in _DATELIKE_DTYPES or is_datetime64_dtype(values):
12541255
_method = _pad_1d_datetime
12551256
elif is_integer_dtype(values):
12561257
values = _ensure_float64(values)
@@ -1259,7 +1260,7 @@ def pad_1d(values, limit=None, mask=None):
12591260
_method = algos.pad_inplace_object
12601261

12611262
if _method is None:
1262-
raise ValueError('Invalid dtype for pad_1d [%s]' % dtype)
1263+
raise ValueError('Invalid dtype for pad_1d [%s]' % dtype.name)
12631264

12641265
if mask is None:
12651266
mask = isnull(values)
@@ -1268,13 +1269,14 @@ def pad_1d(values, limit=None, mask=None):
12681269
return values
12691270

12701271

1271-
def backfill_1d(values, limit=None, mask=None):
1272+
def backfill_1d(values, limit=None, mask=None, dtype=None):
12721273

1273-
dtype = values.dtype.name
1274+
if dtype is None:
1275+
dtype = values.dtype
12741276
_method = None
12751277
if is_float_dtype(values):
1276-
_method = getattr(algos, 'backfill_inplace_%s' % dtype, None)
1277-
elif is_datetime64_dtype(values):
1278+
_method = getattr(algos, 'backfill_inplace_%s' % dtype.name, None)
1279+
elif dtype in _DATELIKE_DTYPES or is_datetime64_dtype(values):
12781280
_method = _backfill_1d_datetime
12791281
elif is_integer_dtype(values):
12801282
values = _ensure_float64(values)
@@ -1283,7 +1285,7 @@ def backfill_1d(values, limit=None, mask=None):
12831285
_method = algos.backfill_inplace_object
12841286

12851287
if _method is None:
1286-
raise ValueError('Invalid dtype for backfill_1d [%s]' % dtype)
1288+
raise ValueError('Invalid dtype for backfill_1d [%s]' % dtype.name)
12871289

12881290
if mask is None:
12891291
mask = isnull(values)
@@ -1293,13 +1295,14 @@ def backfill_1d(values, limit=None, mask=None):
12931295
return values
12941296

12951297

1296-
def pad_2d(values, limit=None, mask=None):
1298+
def pad_2d(values, limit=None, mask=None, dtype=None):
12971299

1298-
dtype = values.dtype.name
1300+
if dtype is None:
1301+
dtype = values.dtype
12991302
_method = None
13001303
if is_float_dtype(values):
1301-
_method = getattr(algos, 'pad_2d_inplace_%s' % dtype, None)
1302-
elif is_datetime64_dtype(values):
1304+
_method = getattr(algos, 'pad_2d_inplace_%s' % dtype.name, None)
1305+
elif dtype in _DATELIKE_DTYPES or is_datetime64_dtype(values):
13031306
_method = _pad_2d_datetime
13041307
elif is_integer_dtype(values):
13051308
values = _ensure_float64(values)
@@ -1308,7 +1311,7 @@ def pad_2d(values, limit=None, mask=None):
13081311
_method = algos.pad_2d_inplace_object
13091312

13101313
if _method is None:
1311-
raise ValueError('Invalid dtype for pad_2d [%s]' % dtype)
1314+
raise ValueError('Invalid dtype for pad_2d [%s]' % dtype.name)
13121315

13131316
if mask is None:
13141317
mask = isnull(values)
@@ -1322,13 +1325,14 @@ def pad_2d(values, limit=None, mask=None):
13221325
return values
13231326

13241327

1325-
def backfill_2d(values, limit=None, mask=None):
1328+
def backfill_2d(values, limit=None, mask=None, dtype=None):
13261329

1327-
dtype = values.dtype.name
1330+
if dtype is None:
1331+
dtype = values.dtype
13281332
_method = None
13291333
if is_float_dtype(values):
1330-
_method = getattr(algos, 'backfill_2d_inplace_%s' % dtype, None)
1331-
elif is_datetime64_dtype(values):
1334+
_method = getattr(algos, 'backfill_2d_inplace_%s' % dtype.name, None)
1335+
elif dtype in _DATELIKE_DTYPES or is_datetime64_dtype(values):
13321336
_method = _backfill_2d_datetime
13331337
elif is_integer_dtype(values):
13341338
values = _ensure_float64(values)
@@ -1337,7 +1341,7 @@ def backfill_2d(values, limit=None, mask=None):
13371341
_method = algos.backfill_2d_inplace_object
13381342

13391343
if _method is None:
1340-
raise ValueError('Invalid dtype for backfill_2d [%s]' % dtype)
1344+
raise ValueError('Invalid dtype for backfill_2d [%s]' % dtype.name)
13411345

13421346
if mask is None:
13431347
mask = isnull(values)
@@ -1503,7 +1507,7 @@ def _interpolate_scipy_wrapper(x, y, new_x, method, fill_value=None,
15031507
return new_y
15041508

15051509

1506-
def interpolate_2d(values, method='pad', axis=0, limit=None, fill_value=None):
1510+
def interpolate_2d(values, method='pad', axis=0, limit=None, fill_value=None, dtype=None):
15071511
""" perform an actual interpolation of values, values will be make 2-d if
15081512
needed fills inplace, returns the result
15091513
"""
@@ -1525,9 +1529,9 @@ def interpolate_2d(values, method='pad', axis=0, limit=None, fill_value=None):
15251529

15261530
method = _clean_fill_method(method)
15271531
if method == 'pad':
1528-
values = transf(pad_2d(transf(values), limit=limit, mask=mask))
1532+
values = transf(pad_2d(transf(values), limit=limit, mask=mask, dtype=dtype))
15291533
else:
1530-
values = transf(backfill_2d(transf(values), limit=limit, mask=mask))
1534+
values = transf(backfill_2d(transf(values), limit=limit, mask=mask, dtype=dtype))
15311535

15321536
# reshape back
15331537
if ndim == 1:

pandas/core/internals.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,12 @@ def _interpolate_with_fill(self, method='pad', axis=0, inplace=False,
878878
fill_value = self._try_fill(fill_value)
879879
values = self.values if inplace else self.values.copy()
880880
values = self._try_operate(values)
881-
values = com.interpolate_2d(values, method, axis, limit, fill_value)
881+
values = com.interpolate_2d(values,
882+
method=method,
883+
axis=axis,
884+
limit=limit,
885+
fill_value=fill_value,
886+
dtype=self.dtype)
882887
values = self._try_coerce_result(values)
883888

884889
blocks = [make_block(values, self.items, self.ref_items,

pandas/tests/test_series.py

+8
Original file line numberDiff line numberDiff line change
@@ -2854,6 +2854,14 @@ def test_datetime64_fillna(self):
28542854
Timestamp('20130103 9:01:01')])
28552855
assert_series_equal(result, expected)
28562856

2857+
# GH 6587
2858+
# make sure that we are treating as integer when filling
2859+
s = Series([pd.NaT, pd.NaT, '2013-08-05 15:30:00.000001'])
2860+
expected = Series(['2013-08-05 15:30:00.000001', '2013-08-05 15:30:00.000001', '2013-08-05 15:30:00.000001'], dtype='M8[ns]')
2861+
result = s.fillna(method='backfill')
2862+
assert_series_equal(result, expected)
2863+
2864+
28572865
def test_fillna_int(self):
28582866
s = Series(np.random.randint(-100, 100, 50))
28592867
s.fillna(method='ffill', inplace=True)

0 commit comments

Comments
 (0)