4545 ensure_index ,
4646 get_objs_combined_axis ,
4747 get_unanimous_names ,
48+ union_indexes ,
4849)
50+ from pandas .core .indexes .datetimes import DatetimeIndex
4951from pandas .core .internals import concatenate_managers
5052
5153if TYPE_CHECKING :
@@ -162,7 +164,7 @@ def concat(
162164 levels = None ,
163165 names : list [HashableT ] | None = None ,
164166 verify_integrity : bool = False ,
165- sort : bool = False ,
167+ sort : bool | lib . NoDefault = lib . no_default ,
166168 copy : bool | lib .NoDefault = lib .no_default ,
167169) -> DataFrame | Series :
168170 """
@@ -405,13 +407,40 @@ def concat(
405407 "Only can inner (intersect) or outer (union) join the other axis"
406408 )
407409
408- if not is_bool (sort ):
410+ objs , keys , ndims = _clean_keys_and_objs (objs , keys )
411+
412+ if sort is lib .no_default :
413+ if axis == 0 :
414+ non_concat_axis = [
415+ obj .columns if isinstance (obj , ABCDataFrame ) else Index ([obj .name ])
416+ for obj in objs
417+ ]
418+ else :
419+ non_concat_axis = [obj .index for obj in objs ]
420+
421+ if (
422+ intersect
423+ or any (not isinstance (index , DatetimeIndex ) for index in non_concat_axis )
424+ or all (
425+ prev is curr for prev , curr in zip (non_concat_axis , non_concat_axis [1 :])
426+ )
427+ or (
428+ all (
429+ prev [- 1 ] <= curr [0 ] and prev .is_monotonic_increasing
430+ for prev , curr in zip (non_concat_axis , non_concat_axis [1 :])
431+ if not prev .empty and not curr .empty
432+ )
433+ and non_concat_axis [- 1 ].is_monotonic_increasing
434+ )
435+ ):
436+ # Sorting or not will not impact the result.
437+ sort = False
438+ elif not is_bool (sort ):
409439 raise ValueError (
410440 f"The 'sort' keyword only accepts boolean values; { sort } was passed."
411441 )
412- sort = bool (sort )
413-
414- objs , keys , ndims = _clean_keys_and_objs (objs , keys )
442+ else :
443+ sort = bool (sort )
415444
416445 # select an object to be our result reference
417446 sample , objs = _get_sample_object (objs , ndims , keys , names , levels , intersect )
@@ -436,9 +465,10 @@ def concat(
436465 if len (ndims ) > 1 :
437466 objs = _sanitize_mixed_ndim (objs , sample , ignore_index , bm_axis )
438467
468+ orig_axis = axis
439469 axis = 1 - bm_axis if is_frame else 0
440470 names = names or getattr (keys , "names" , None )
441- return _get_result (
471+ result = _get_result (
442472 objs ,
443473 is_series ,
444474 bm_axis ,
@@ -452,6 +482,28 @@ def concat(
452482 axis ,
453483 )
454484
485+ if sort is lib .no_default :
486+ if orig_axis == 0 :
487+ non_concat_axis = [
488+ obj .columns if isinstance (obj , ABCDataFrame ) else Index ([obj .name ])
489+ for obj in objs
490+ ]
491+ else :
492+ non_concat_axis = [obj .index for obj in objs ]
493+ no_sort_result_index = union_indexes (non_concat_axis , sort = False )
494+ orig = result .index if orig_axis == 1 else result .columns
495+ if not no_sort_result_index .equals (orig ):
496+ msg = (
497+ "Sorting by default when concatenating all DatetimeIndex is "
498+ "deprecated. In the future, pandas will respect the default "
499+ "of `sort=False`. Specify `sort=True` or `sort=False` to "
500+ "silence this message. If you see this warnings when not "
501+ "directly calling concat, report a bug to pandas."
502+ )
503+ warnings .warn (msg , Pandas4Warning , stacklevel = find_stack_level ())
504+
505+ return result
506+
455507
456508def _sanitize_mixed_ndim (
457509 objs : list [Series | DataFrame ],
@@ -510,7 +562,7 @@ def _get_result(
510562 bm_axis : AxisInt ,
511563 ignore_index : bool ,
512564 intersect : bool ,
513- sort : bool ,
565+ sort : bool | lib . NoDefault ,
514566 keys : Iterable [Hashable ] | None ,
515567 levels ,
516568 verify_integrity : bool ,
@@ -620,7 +672,7 @@ def new_axes(
620672 objs : list [Series | DataFrame ],
621673 bm_axis : AxisInt ,
622674 intersect : bool ,
623- sort : bool ,
675+ sort : bool | lib . NoDefault ,
624676 keys : Iterable [Hashable ] | None ,
625677 names : list [HashableT ] | None ,
626678 axis : AxisInt ,
0 commit comments