|
7 | 7 |
|
8 | 8 | import numpy as np
|
9 | 9 |
|
10 |
| -from pandas._libs import lib, tslib, tslibs |
| 10 | +from pandas._libs import NaT, lib, tslib, tslibs |
11 | 11 | import pandas._libs.internals as libinternals
|
12 | 12 | from pandas._libs.tslibs import Timedelta, conversion, is_null_datetimelike
|
13 | 13 | from pandas.util._validators import validate_bool_kwarg
|
@@ -405,33 +405,29 @@ def fillna(self, value, limit=None, inplace=False, downcast=None):
|
405 | 405 | else:
|
406 | 406 | return self.copy()
|
407 | 407 |
|
408 |
| - # fillna, but if we cannot coerce, then try again as an ObjectBlock |
409 |
| - try: |
410 |
| - # Note: we only call try_coerce_args to let it raise |
411 |
| - self._try_coerce_args(value) |
412 |
| - except (TypeError, ValueError): |
413 |
| - |
414 |
| - # we can't process the value, but nothing to do |
415 |
| - if not mask.any(): |
416 |
| - return self if inplace else self.copy() |
417 |
| - |
418 |
| - # operate column-by-column |
419 |
| - def f(m, v, i): |
420 |
| - block = self.coerce_to_target_dtype(value) |
421 |
| - |
422 |
| - # slice out our block |
423 |
| - if i is not None: |
424 |
| - block = block.getitem_block(slice(i, i + 1)) |
425 |
| - return block.fillna(value, limit=limit, inplace=inplace, downcast=None) |
426 |
| - |
427 |
| - return self.split_and_operate(mask, f, inplace) |
428 |
| - else: |
| 408 | + if self._can_hold_element(value): |
| 409 | + # equivalent: self._try_coerce_args(value) would not raise |
429 | 410 | blocks = self.putmask(mask, value, inplace=inplace)
|
430 | 411 | blocks = [
|
431 | 412 | b.make_block(values=self._try_coerce_result(b.values)) for b in blocks
|
432 | 413 | ]
|
433 | 414 | return self._maybe_downcast(blocks, downcast)
|
434 | 415 |
|
| 416 | + # we can't process the value, but nothing to do |
| 417 | + if not mask.any(): |
| 418 | + return self if inplace else self.copy() |
| 419 | + |
| 420 | + # operate column-by-column |
| 421 | + def f(m, v, i): |
| 422 | + block = self.coerce_to_target_dtype(value) |
| 423 | + |
| 424 | + # slice out our block |
| 425 | + if i is not None: |
| 426 | + block = block.getitem_block(slice(i, i + 1)) |
| 427 | + return block.fillna(value, limit=limit, inplace=inplace, downcast=None) |
| 428 | + |
| 429 | + return self.split_and_operate(mask, f, inplace) |
| 430 | + |
435 | 431 | def split_and_operate(self, mask, f, inplace):
|
436 | 432 | """
|
437 | 433 | split the block per-column, and apply the callable f
|
@@ -2275,7 +2271,13 @@ def _can_hold_element(self, element):
|
2275 | 2271 | tipo = maybe_infer_dtype_type(element)
|
2276 | 2272 | if tipo is not None:
|
2277 | 2273 | return tipo == _NS_DTYPE or tipo == np.int64
|
2278 |
| - return is_integer(element) or isinstance(element, datetime) or isna(element) |
| 2274 | + if isinstance(element, datetime): |
| 2275 | + return element.tzinfo is None |
| 2276 | + if is_integer(element): |
| 2277 | + return element == tslibs.iNaT |
| 2278 | + |
| 2279 | + # TODO: shouldnt we exclude timedelta64("NaT")? See GH#27297 |
| 2280 | + return isna(element) |
2279 | 2281 |
|
2280 | 2282 | def _coerce_values(self, values):
|
2281 | 2283 | return values.view("i8")
|
@@ -2627,6 +2629,8 @@ def _can_hold_element(self, element):
|
2627 | 2629 | tipo = maybe_infer_dtype_type(element)
|
2628 | 2630 | if tipo is not None:
|
2629 | 2631 | return issubclass(tipo.type, (np.timedelta64, np.int64))
|
| 2632 | + if element is NaT: |
| 2633 | + return True |
2630 | 2634 | return is_integer(element) or isinstance(
|
2631 | 2635 | element, (timedelta, np.timedelta64, np.int64)
|
2632 | 2636 | )
|
|
0 commit comments