Skip to content

Commit c463cfb

Browse files
Charlie-XIAOlithomas1
authored andcommitted
Backport PR pandas-dev#53641: BUG: pd.concat dataframes with different datetime64 resolutions
1 parent f99a1fc commit c463cfb

File tree

2 files changed

+51
-14
lines changed

2 files changed

+51
-14
lines changed

pandas/core/dtypes/concat.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,16 @@ def concat_compat(
129129
# i.e. isinstance(to_concat[0], ExtensionArray)
130130
to_concat_eas = cast("Sequence[ExtensionArray]", to_concat)
131131
cls = type(to_concat[0])
132-
return cls._concat_same_type(to_concat_eas)
132+
# GH#53640: eg. for datetime array, axis=1 but 0 is default
133+
# However, class method `_concat_same_type()` for some classes
134+
# may not support the `axis` keyword
135+
if ea_compat_axis or axis == 0:
136+
return cls._concat_same_type(to_concat_eas)
137+
else:
138+
return cls._concat_same_type(
139+
to_concat_eas,
140+
axis=axis, # type: ignore[call-arg]
141+
)
133142
else:
134143
to_concat_arrs = cast("Sequence[np.ndarray]", to_concat)
135144
result = np.concatenate(to_concat_arrs, axis=axis)

pandas/tests/reshape/concat/test_datetimes.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@
1919
)
2020
import pandas._testing as tm
2121

22+
UNITS = ["s", "ms", "us", "ns"]
23+
24+
25+
@pytest.fixture(params=UNITS)
26+
def unit(request):
27+
return request.param
28+
29+
30+
unit2 = unit
31+
32+
33+
def _get_finer_unit(unit, unit2):
34+
if UNITS.index(unit) >= UNITS.index(unit2):
35+
return unit
36+
return unit2
37+
2238

2339
class TestDatetimeConcat:
2440
def test_concat_datetime64_block(self):
@@ -305,46 +321,58 @@ def test_concat_tz_series(self):
305321
result = concat([x, y], ignore_index=True)
306322
tm.assert_series_equal(result, expected)
307323

324+
def test_concat_tz_series3(self, unit, unit2):
308325
# see gh-12217 and gh-12306
309326
# Concatenating two UTC times
310-
first = DataFrame([[datetime(2016, 1, 1)]])
327+
first = DataFrame([[datetime(2016, 1, 1)]], dtype=f"M8[{unit}]")
311328
first[0] = first[0].dt.tz_localize("UTC")
312329

313-
second = DataFrame([[datetime(2016, 1, 2)]])
330+
second = DataFrame([[datetime(2016, 1, 2)]], dtype=f"M8[{unit2}]")
314331
second[0] = second[0].dt.tz_localize("UTC")
315332

316333
result = concat([first, second])
317-
assert result[0].dtype == "datetime64[ns, UTC]"
334+
exp_unit = _get_finer_unit(unit, unit2)
335+
assert result[0].dtype == f"datetime64[{exp_unit}, UTC]"
318336

337+
def test_concat_tz_series4(self, unit, unit2):
319338
# Concatenating two London times
320-
first = DataFrame([[datetime(2016, 1, 1)]])
339+
first = DataFrame([[datetime(2016, 1, 1)]], dtype=f"M8[{unit}]")
321340
first[0] = first[0].dt.tz_localize("Europe/London")
322341

323-
second = DataFrame([[datetime(2016, 1, 2)]])
342+
second = DataFrame([[datetime(2016, 1, 2)]], dtype=f"M8[{unit2}]")
324343
second[0] = second[0].dt.tz_localize("Europe/London")
325344

326345
result = concat([first, second])
327-
assert result[0].dtype == "datetime64[ns, Europe/London]"
346+
exp_unit = _get_finer_unit(unit, unit2)
347+
assert result[0].dtype == f"datetime64[{exp_unit}, Europe/London]"
328348

349+
def test_concat_tz_series5(self, unit, unit2):
329350
# Concatenating 2+1 London times
330-
first = DataFrame([[datetime(2016, 1, 1)], [datetime(2016, 1, 2)]])
351+
first = DataFrame(
352+
[[datetime(2016, 1, 1)], [datetime(2016, 1, 2)]], dtype=f"M8[{unit}]"
353+
)
331354
first[0] = first[0].dt.tz_localize("Europe/London")
332355

333-
second = DataFrame([[datetime(2016, 1, 3)]])
356+
second = DataFrame([[datetime(2016, 1, 3)]], dtype=f"M8[{unit2}]")
334357
second[0] = second[0].dt.tz_localize("Europe/London")
335358

336359
result = concat([first, second])
337-
assert result[0].dtype == "datetime64[ns, Europe/London]"
360+
exp_unit = _get_finer_unit(unit, unit2)
361+
assert result[0].dtype == f"datetime64[{exp_unit}, Europe/London]"
338362

339-
# Concat'ing 1+2 London times
340-
first = DataFrame([[datetime(2016, 1, 1)]])
363+
def test_concat_tz_series6(self, unit, unit2):
364+
# Concatenating 1+2 London times
365+
first = DataFrame([[datetime(2016, 1, 1)]], dtype=f"M8[{unit}]")
341366
first[0] = first[0].dt.tz_localize("Europe/London")
342367

343-
second = DataFrame([[datetime(2016, 1, 2)], [datetime(2016, 1, 3)]])
368+
second = DataFrame(
369+
[[datetime(2016, 1, 2)], [datetime(2016, 1, 3)]], dtype=f"M8[{unit2}]"
370+
)
344371
second[0] = second[0].dt.tz_localize("Europe/London")
345372

346373
result = concat([first, second])
347-
assert result[0].dtype == "datetime64[ns, Europe/London]"
374+
exp_unit = _get_finer_unit(unit, unit2)
375+
assert result[0].dtype == f"datetime64[{exp_unit}, Europe/London]"
348376

349377
def test_concat_tz_series_tzlocal(self):
350378
# see gh-13583

0 commit comments

Comments
 (0)