|
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