BUG: Handle Datetimelike data in DataFrame.combine
State: closed

Closes https://github.com/pandas-dev/pandas/issues/23079

Labels:
name: Dtype Conversions
description: Unexpected or buggy dtype conversions

Comments:
Hello @TomAugspurger! Thanks for submitting the PR.

 - There are no PEP8 issues in the file [`pandas/core/frame.py`](https://github.com/TomAugspurger/pandas/blob/4c0f4930c02ae8172b986e98bb7c64f7b79c2047/pandas/core/frame.py) !

 - There are no PEP8 issues in the file [`pandas/tests/frame/test_combine_concat.py`](https://github.com/TomAugspurger/pandas/blob/4c0f4930c02ae8172b986e98bb7c64f7b79c2047/pandas/tests/frame/test_combine_concat.py) !


After this, we'll need an additional change on the PeriodArray PR, so that the integers are converted back to periods:

```diff
commit f73f83e2878e04d266d8f86c2675d6c1fae6d90e
Author: Tom Augspurger <tom.w.augspurger@gmail.com>
Date:   Wed Oct 24 11:28:59 2018 -0500

    TST: Unxfail combine

diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py
index 56bf39472..46c8126f6 100644
--- a/pandas/core/dtypes/cast.py
+++ b/pandas/core/dtypes/cast.py
@@ -6,7 +6,7 @@ import numpy as np
 import warnings
 
 from pandas._libs import tslib, lib, tslibs
-from pandas._libs.tslibs import iNaT, OutOfBoundsDatetime
+from pandas._libs.tslibs import iNaT, OutOfBoundsDatetime, Period
 from pandas.compat import string_types, text_type, PY3
 from .common import (ensure_object, is_bool, is_integer, is_float,
                      is_complex, is_datetimetz, is_categorical_dtype,
@@ -164,6 +164,12 @@ def maybe_downcast_to_dtype(result, dtype):
                     result = to_datetime(result).tz_localize('utc')
                     result = result.tz_convert(dtype.tz)
 
+        elif dtype.type == Period:
+            # TODO(DatetimeArray): merge with previous elif
+            from pandas.core.arrays import PeriodArray
+
+            return PeriodArray(result, freq=dtype.freq)
+
     except Exception:
         pass
 
diff --git a/pandas/tests/frame/test_combine_concat.py b/pandas/tests/frame/test_combine_concat.py
index 2803db4f4..3b8d6e6c5 100644
--- a/pandas/tests/frame/test_combine_concat.py
+++ b/pandas/tests/frame/test_combine_concat.py
@@ -759,7 +759,6 @@ class TestDataFrameCombineFirst(TestData):
         tm.assert_frame_equal(res, exp)
         assert res['TD'].dtype == 'timedelta64[ns]'
 
-    @pytest.mark.xfail(reason="GH-23079", strict=True)
     def test_combine_first_period(self):
         data1 = pd.PeriodIndex(['2011-01', 'NaT', '2011-03',
                                 '2011-04'], freq='M')
```
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/23317?src=pr&el=h1) Report
> Merging [#23317](https://codecov.io/gh/pandas-dev/pandas/pull/23317?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/1c26375c0743a2cbdcfe14a62ad10806001cbee8?src=pr&el=desc) will **decrease** coverage by `<.01%`.
> The diff coverage is `93.33%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/23317/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/23317?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #23317      +/-   ##
==========================================
- Coverage   92.22%   92.22%   -0.01%     
==========================================
  Files         169      169              
  Lines       50911    50914       +3     
==========================================
+ Hits        46954    46956       +2     
- Misses       3957     3958       +1
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.65% <93.33%> (-0.01%)` | :arrow_down: |
| #single | `42.29% <0%> (-0.01%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/23317?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/23317/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `96.98% <93.33%> (-0.05%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/23317?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/23317?src=pr&el=footer). Last update [1c26375...b659913](https://codecov.io/gh/pandas-dev/pandas/pull/23317?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

@jreback do you have a chance to look at this? It's one of the blockers for PeriodArray.

Originally, this was done as part of 
https://github.com/pandas-dev/pandas/pull/3595. I think the conversion of i8 needs to happen inside the `combiner` function, not outside of it.

Actually... one sec, this may not be a blocker.
Oh, yes, it is kinda a blocker, but I mis-diagnosed the real issue. The real thing we need on the PeriodArray PR is the change in `maybe_downcast_to_dtype` turning the i8 array back into a PeriodArray. But we'll still need this so that we handle the unpacking from series correctly.

So, I think this is still a valuable change on its own.
might be some more issues about this (which this may fix)
Didn't see any other issues that this fixes. https://github.com/pandas-dev/pandas/issues/7509 is still broken with this PR.
thanks @TomAugspurger