Skip to content

Commit 9ba4ef8

Browse files
authored
PERF: concat_compat (#52316)
1 parent 5ea5570 commit 9ba4ef8

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

pandas/_libs/lib.pyx

+3
Original file line numberDiff line numberDiff line change
@@ -3060,6 +3060,9 @@ def dtypes_all_equal(list types not None) -> bool:
30603060
"""
30613061
first = types[0]
30623062
for t in types[1:]:
3063+
if t is first:
3064+
# Fastpath can provide a nice boost for EADtypes
3065+
continue
30633066
try:
30643067
if not t == first:
30653068
return False

pandas/core/dtypes/concat.py

+20
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
import numpy as np
1313

14+
from pandas._libs import lib
15+
1416
from pandas.core.dtypes.astype import astype_array
1517
from pandas.core.dtypes.cast import (
1618
common_dtype_categorical_compat,
@@ -60,6 +62,24 @@ def concat_compat(
6062
-------
6163
a single array, preserving the combined dtypes
6264
"""
65+
if len(to_concat) and lib.dtypes_all_equal([obj.dtype for obj in to_concat]):
66+
# fastpath!
67+
obj = to_concat[0]
68+
if isinstance(obj, np.ndarray):
69+
to_concat_arrs = cast("Sequence[np.ndarray]", to_concat)
70+
return np.concatenate(to_concat_arrs, axis=axis)
71+
72+
to_concat_eas = cast("Sequence[ExtensionArray]", to_concat)
73+
if ea_compat_axis:
74+
# We have 1D objects, that don't support axis keyword
75+
return obj._concat_same_type(to_concat_eas)
76+
elif axis == 0:
77+
return obj._concat_same_type(to_concat_eas)
78+
else:
79+
# e.g. DatetimeArray
80+
# NB: We are assuming here that ensure_wrapped_if_arraylike has
81+
# been called where relevant.
82+
return obj._concat_same_type(to_concat_eas, axis=axis)
6383

6484
# filter empty arrays
6585
# 1-d dtypes always are included here

pandas/core/internals/concat.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,12 @@ def concatenate_managers(
230230
# we can use np.concatenate, which is more performant
231231
# than concat_compat
232232
values = np.concatenate(vals, axis=1)
233-
else:
233+
elif is_1d_only_ea_dtype(blk.dtype):
234234
# TODO(EA2D): special-casing not needed with 2D EAs
235-
values = concat_compat(vals, axis=1)
235+
values = concat_compat(vals, axis=1, ea_compat_axis=True)
236236
values = ensure_block_shape(values, ndim=2)
237+
else:
238+
values = concat_compat(vals, axis=1)
237239

238240
values = ensure_wrapped_if_datetimelike(values)
239241

@@ -541,6 +543,9 @@ def get_reindexed_values(self, empty_dtype: DtypeObj, upcasted_na) -> ArrayLike:
541543
# if we did, the missing_arr.fill would cast to gibberish
542544
missing_arr = np.empty(self.shape, dtype=empty_dtype)
543545
missing_arr.fill(fill_value)
546+
547+
if empty_dtype.kind in "mM":
548+
missing_arr = ensure_wrapped_if_datetimelike(missing_arr)
544549
return missing_arr
545550

546551
if (not self.indexers) and (not self.block._can_consolidate):

0 commit comments

Comments
 (0)