Repository: pandas-dev/pandas
Pull request #58119 (2024-04-02 18:13:03)

PERF: concat([Series, DataFrame], axis=0) returns RangeIndex columns when possible
Discovered in #57441

WillAyd: Conflict but otherwise lgtm

Patch:
diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml
index d6cfd3b0ad..4bd9068e91 100644
--- a/.github/workflows/wheels.yml
+++ b/.github/workflows/wheels.yml
@@ -139,8 +139,7 @@ jobs:
         shell: bash -el {0}
         run: echo "sdist_name=$(cd ./dist && ls -d */)" >> "$GITHUB_ENV"
 
-      - name: Build normal wheels
-        if: ${{ (env.IS_SCHEDULE_DISPATCH != 'true' || env.IS_PUSH == 'true') }}
+      - name: Build wheels
         uses: pypa/cibuildwheel@v2.17.0
         with:
          package-dir: ./dist/${{ startsWith(matrix.buildplat[1], 'macosx') && env.sdist_name || needs.build_sdist.outputs.sdist_file }}
diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst
index 78ee359397..d2d5707f32 100644
--- a/doc/source/whatsnew/v3.0.0.rst
+++ b/doc/source/whatsnew/v3.0.0.rst
@@ -298,6 +298,7 @@ Performance improvements
 - :attr:`Categorical.categories` returns a :class:`RangeIndex` columns instead of an :class:`Index` if the constructed ``values`` was a ``range``. (:issue:`57787`)
 - :class:`DataFrame` returns a :class:`RangeIndex` columns when possible when ``data`` is a ``dict`` (:issue:`57943`)
 - :class:`Series` returns a :class:`RangeIndex` index when possible when ``data`` is a ``dict`` (:issue:`58118`)
+- :func:`concat` returns a :class:`RangeIndex` column when possible when ``objs`` contains :class:`Series` and :class:`DataFrame` and ``axis=0`` (:issue:`58119`)
 - :func:`concat` returns a :class:`RangeIndex` level in the :class:`MultiIndex` result when ``keys`` is a ``range`` or :class:`RangeIndex` (:issue:`57542`)
 - :meth:`RangeIndex.append` returns a :class:`RangeIndex` instead of a :class:`Index` when appending values that could continue the :class:`RangeIndex` (:issue:`57467`)
 - :meth:`Series.str.extract` returns a :class:`RangeIndex` columns instead of an :class:`Index` column when possible (:issue:`57542`)
diff --git a/pandas/core/reshape/concat.py b/pandas/core/reshape/concat.py
index 0868f71109..d17e5b475a 100644
--- a/pandas/core/reshape/concat.py
+++ b/pandas/core/reshape/concat.py
@@ -518,8 +518,11 @@ class _Concatenator:
                         # to have unique names
                         name = current_column
                         current_column += 1
-
-                obj = sample._constructor({name: obj}, copy=False)
+                    obj = sample._constructor(obj, copy=False)
+                    if isinstance(obj, ABCDataFrame):
+                        obj.columns = range(name, name + 1, 1)
+                else:
+                    obj = sample._constructor({name: obj}, copy=False)
 
             new_objs.append(obj)
 


Test patch:
diff --git a/pandas/tests/reshape/concat/test_concat.py b/pandas/tests/reshape/concat/test_concat.py
index b986aa8182..92e7567565 100644
--- a/pandas/tests/reshape/concat/test_concat.py
+++ b/pandas/tests/reshape/concat/test_concat.py
@@ -912,3 +912,11 @@ def test_concat_none_with_timezone_timestamp():
         result = concat([df1, df2], ignore_index=True)
     expected = DataFrame({"A": [None, pd.Timestamp("1990-12-20 00:00:00+00:00")]})
     tm.assert_frame_equal(result, expected)
+
+
+def test_concat_with_series_and_frame_returns_rangeindex_columns():
+    ser = Series([0])
+    df = DataFrame([1, 2])
+    result = concat([ser, df])
+    expected = DataFrame([0, 1, 2], index=[0, 0, 1])
+    tm.assert_frame_equal(result, expected, check_column_type=True)